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:

  1. Download and extract the Xajax archive
  2. Place the PHP files somewhere in the include_path of your application
  3. Rename xajax.inc.php to Xajax.php, now the Zend Framework autoload mechanism is able to find your Xajax class
  4. Place the Javascript file somewhere publicly accessible (for example: /public_html/public/javascript/xajax_js/)
  5. 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.

/*
     *
     * 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:'.$urlZend_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:'.$urlZend_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:'.$urlZend_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: '.$eZend_Log::CRIT);
                //Navigate to the ErrorController::failure() method
                $this->navigate('error/failure');
            }//catch
        }//else
    }//function