Xajax (any): Tips and Tricks: Using xajax with the Zend framework
Xajax (any): Tips and Tricks: Using xajax with the Zend framework
[edit] Zend_Filter_Input clears $_GET and $_POST
Xajax can be used in combination with the Zend Framework. The following tips and tricks are based on discussions in the Xajax Community Forums
(posted by CrazyLegz on the Xajax forum)
I'm using Zend Framework 0.8.0 and xajax 0.2.4
After examening processRequests() method in the xajax class I found out that processRequests is calling the getRequestMode method. This method returned -1 wich means $_POST["xajax"] and $_GET["xajax"] are empty.
If getRequestMode returns -1 it exits before is has done something at all. So this means your Ajax call isn't processed.
In my case this was very logical. In my index.php bootstrap file I had the following two lines.
Zend::register("post", new Zend_Filter_Input($_POST));
Zend::register("get", new Zend_Filter_Input($_GET));
The $_POST and $_GET arrays are set to NULL by Zend_Filter_Input.
So $_POST["xajax"] will never get to processRequests of the xajax class.
You can resolve this by changing the two lines to the following two lines:
Zend::register("post", new Zend_Filter_Input($_POST, false));
Zend::register("get", new Zend_Filter_Input($_GET, false));
In this way the $_POST and $_GET arrays are left intact.
Note that the new 1.0 version of the Zend Framework does not use the Zend_Filter_Input anymore. Filtering of GET and POST requests can be done by:
$htmlEntities = new Zend_Filter_HtmlEntities();
$filteredGet = array();
$filteredPost = array();
while(list($key, $value) = each($_GET)){
if(is_string($value))$filteredGet[$key] = $htmlEntities->filter($value);
else $filteredGet[$key] = $value;
}
while(list($key, $value) = each($_POST)){
if(is_string($value))$filteredPost[$key] = $htmlEntities->filter($value);
else $filteredPost[$key] = $value;
}
Zend_Registry::set("get", $filteredGet);
Zend_Registry::set("post", $filteredPost);
[edit] Opening up functionality in Zend Framework controllers to Xajax
Based on a discussion on the Xajax Forum
- Zend Framework: 1.0.3
- Xajax: 0.5 beta 4b
Instructions:
- Download and extract the Xajax archive
- Place the PHP files somewhere in the include_path of your application
- Rename xajax.inc.php to Xajax.php, now the Zend Framework autoload mechanism is able to find your Xajax class
- Place the Javascript file somewhere publicly accessible (for example: /public_html/public/javascript/xajax_js/)
- Now add a controller: 'XajaxController' that takes care of incoming Xajax requests:
<?php class XajaxController extends Zend_Controller_Action { /** * Processes incoming xajax requests * */ public function processAction() { $xajax = new xajax(); $xajax->processRequest(); } }
6. Determine what functionality should be opened up by Xajax by making some dedicated Xajax-Controllers. These controllers can be fitted with a constructor which makes it some easier to initialize:
<?php class XajaxTestController extends Zend_Controller_Action { /** * The XajaxResponse that will eventually be returned * * @var Object XajaxResponse */ private $_xajaxResponse; /** * A constructor is usefull when not all required parameters of Zend_Controller_Action are available * * @param Zend_Controller_Request_Http $request * @param Zend_Controller_Response_Http $response * @param array $invokeArgs */ public function __construct($request = false, $response = false, $invokeArgs = false) { if(!$request) $request = new Zend_Controller_Request_Http(); if(!$response) $response = new Zend_Controller_Response_Http(); if(!$invokeArgs) $invokeArgs = array(); parent::__construct($request, $response, $invokeArgs); } public function init() { $this->_xajaxResponse = new xajaxResponse(); } /** * Perform some action and return a Xajax response * * @param Array $formValues The form values as posted by xajax * @return Object $this->_xajaxResponse Xajax response */ public function hello($formValues) { $this->_xajaxResponse->assign('content', 'innerHTML', 'New content goes here!'); return $this->_xajaxResponse; } }
7. In your bootstrap index.php or configuration plugin, initialize and configure Xajax.
$xajax = new Xajax(); //The request URI is the webserver's path to the XajaxController::processAction() method $xajax->configure('requestURI', 'http://servername/application/xajax/process/'); /** * Now we should initialize the XajaxTestController, since we have added a constructor * to this controller, we can do this in various ways, for example: * - directly from the bootstrap, do not pass a parameter for the request * - or when you use a plugin that extends the Zend_Controller_Plugin_Abstract, * you can re-use the Zend_Controller_Request_Http() object that is handed over to * the plugin, for instance in the routeShutdown($request) method. This has some advantages * since your XajaxTestController can re-use this request including parameters such as views, * logging functionality et. cetera as well. */ $xajaxTestController = new XajaxTestController(); //in the bootstrap $xajaxTestController = new XajaxTestController($request); //when you use a ZF plugin /** * Now register the functions which should be available clientside, the function will * be available in JavaScript the way you name the first parameter, prefixed by 'xajax_' * in this case: 'xajax_hello' points to XajaxTestController::hello() */ $xajax->register(XAJAX_FUNCTION, array('testHello', &$xajaxTestController, 'hello')); //Finally acquire the JavaScript which should be printed in the output / view $javaScriptString = $xajax->getJavascript('http://servername/application/public/javascript/');
Now one should be able to use the xajax_hello() Javascript function, which is and processed by the XajaxController::processAction().
[edit] Using Xajax for navigation purposes in the Zend Framework
Xajax can be used for navigation purposes in the Zend Framework. One can add a navigation method which can be invoked using javascript and which will set up a new routing request. Eventually the returned content is handed over to Xajax. Using the Xajax dhtmlHistory extension, the user is still able to use the browsers 'back' button.
- Zend Framework: 1.0.3
- Xajax: 0.5 beta 4b
- Xajax dhtmlHistory extenstion 0.6 - Backbutton plugin
/* * * Function to easily navigate to a page, it is actually a second bootstrap which receives, routes and dispatches requests * * @param String $url (for example 'user/add/id/10/') * @return object XajaxResponse */ public function navigate($url) { $frontController = Zend_Controller_Front::getInstance(); $request = $frontController->getRequest(); $request->setPathInfo('/'.$url); $this->_logger->log(__METHOD__.': received navigation request for url:'.$url, Zend_Log::DEBUG); $router = new Zend_Controller_Router_Rewrite(); $dispatcher = $frontController->getDispatcher(); //When the request is not dispatchable, use the IndexController::noroute() method if (!$dispatcher->isDispatchable($request)){ $request->setControllerName('index'); $request->setActionName('noroute'); $this->_logger->log(__METHOD__.': request is not dispatchable, received url:'.$url, Zend_Log::DEBUG); $this->_xajaxResponse->assign('xajaxStatus','innerHTML','Provided URL not dispatchable'); }//if else{ $frontController->setRouter($router) ->setDispatcher($dispatcher) ->setControllerDirectory(array('default' => './private/default/php/controllers')) ->setParam('noViewRenderer', true) //required to disable the view renderer introduced in ZF 1.0.0-RC1, ->returnResponse(true) ->throwExceptions(true); try { //A Zend_Http_Response object is returned, fetch the body $httpResponse = $frontController->dispatch($request); $body = $httpResponse->getBody(); //Store the url as a waypoint $sWaypointName = $url; //Possibly some data needs to be stored with the waypoint $aWaypointData = array('my data to recover','this waypoint'); //Add the waypoint to the navigation history dhtmlHistoryAdd($this->_xajaxResponse, $sWaypointName, $aWaypointData); $this->_xajaxResponse->assign('content','innerHTML',$body); $this->_xajaxResponse->assign('xajaxStatus','innerHTML', 'Url loaded'); $this->_logger->log(__METHOD__.': dispatched:'.$url, Zend_Log::DEBUG); } catch (Exception $e) { $this->_logger->log(__METHOD__.': received exception from the Xajax navigation bootstrap, redirecting to the errorController and passing on the error message: '.$e, Zend_Log::CRIT); //Navigate to the ErrorController::failure() method $this->navigate('error/failure'); }//catch }//else }//function