Dynamic Module Switching in Zend Framework

Recently I ran into the problem of needing to switch the module part of a request depending on the hostname. I needed to do this because I plugged in a whitelabeling solution to our existing web application. When the request comes in, I needed to switch from the default module to the whitelabel module so that app routing would work. I’m not 100% sure that this is the best way to go for this scenario, but this is the only way I could think of doing it. I’d be interested in finding out any alternatives to this method.

I solved this problem by creating an action helper with a preDispatch() hook that would switch the module depending on the hostname. If you want the hooks to work you need to instantiate the helper in the bootstrap, otherwise it won’t work since helpers are lazy loaded.. This article has more details about action helpers, but it’s a bit dated - http://devzone.zend.com/1218/action-helpers-in-zend-framework/

Create the Action Helper

class My_Controller_Action_Helper_Whitelabel extends Zend_Controller_Action_Helper_Abstract {

    public function preDispatch() {
        /**
         * Here we want to check whether this is a whitelabel url, and if so switch the module.
         */
        if ($this->isWhitelabelUrl() && $this->getRequest()->getModuleName() == 'default') {
            $this->getRequest()->setModuleName('whitelabel');
            $this->getRequest()->setDispatched(false);
        }
    }

    /**
     * Checks whether the current host is a whitelabel or not
     * @return boolean
     */
    private function isWhitelabelUrl() {
        //code to check condition
    }
}

Note that ‘My’ is just a namespace I use. You can even put this inside your application folder and not in a separate library folder. You can read this question on SO for more information - http://stackoverflow.com/questions/4701177/zend-action-helper.

$this->getRequest()->setModuleName('whitelabel');
$this->getRequest()->setDispatched(false);

Switching modules only takes two lines,  the first line resets the module and the second line sets the dispatched flag for the request. If you don’t set the dispatched flag to false, Zend will just serve the default module. Keep in mind that if you don’t have the conditional, Zend will simply get into a loop because it will keep trying to dispatch the request over and over again.

Now that you have the action helper created, you need to hook it into the bootstrap file so that an instance of the helper is loaded when your application is loaded. You need to do this because you need the preDispatch() hook to be fired during the normal routing process.

Initialize in Bootstrap

In my Bootstrap.php file, I have a _initApplication() method which is fired when the application is loaded. I’ve put the instantiation code for the helper in that method.

public function _initApplication() {
    //code
    Zend_Controller_Action_HelperBroker::addHelper(
        new My_Controller_Action_Helper_Whitelabel()
    );
}

This creates an instance of our whitelabel helper and Zend will execute the code in the hooks at the proper time.

Something I have to look into is, how routing is affected when I set ‘dispatched’ to false. I haven’t found enough information on this yet, but will update this space if and when I find more.

Debugging Tips for Beginners

A common type of question I find on Stack Overflow are beginners having trouble with figuring out why their AJAX application / functionality isn’t working. They usually go something like this…

I have two input boxes which accept the username and password and sends it to the PHP login page via AJAX. But when I type in my credentials, I don’t get logged in. Why isn’t it working?

When starting out to fix a problem, you need to first find out what the problem is. To do that you need to isolate where the problem lies, so break it down into its individual components. In no particular order, these would be

  • The Javascript and AJAX
  • The PHP and server side code
  • The DOM and HTML
Let’s look at each of them in a bit more detail

The Javascript

I do my development on Firefox because I’ve found it has the best addons for the job. If you haven’t already, install Firebug for Firefox. In the page that has the AJAX functionality, open the Firebug console by hitting F12. Make sure the console is enabled (a reload of the page may be required) and carry out the action that triggers the AJAX response. If your JS code works, you should see something like the following in the console.
Firebug console in action

Firebug console in action

If you see any error messages or ‘not founds’ for any of your requests, then you have a problem. Clicking on the request allows you to confirm that the correct request and response is happening in your application. If the requests and responses are correct, then your problem lies in either the HTML or your JS callback.
If you’re getting 404 messages for the request, that mean the PHP file you’re pointing to doesn’t exist. Update your code to fix the problem. Do the same if you’re seeing JS error messages. Make good use of the console (which can run live JS that affects your page) and the debugger (where you can walk through your JS files) .
If on the other hand, your request is sent properly but the response is incorrect then you need to look at your PHP page.

The PHP and Server Side Code

When you work with AJAX, it helps if you make sure that your application works without AJAX initially. This serves the double purpose of making sure your core functionality works and having a fallback when Javascript is disabled. Assuming you’re working with GET and not POST, either copy the request URL from Firebug or craft your own and access it in the browser. If you get an error then you’ve isolated (one of) your problem(s)! Find out what’s wrong and fix it and then see if the AJAX functionality works.

Using an IDE when coding gives you many benefits. Although you may think that notepad might be enough for your needs, something like Eclipse (which I use) or NetBeans (which I’ve used) can come in very handy to catch some problems as you code them.

And don’t forget to have a debugger setup. I mainly use Xdebug, but you can just as easily use ZendDebug.

Once you make sure you have the JS async call working properly with the serverside PHP script, you can look at the callback and the DOM.

The DOM and HTML

The most common reason for AJAX updates not working on the client side is usually because the element you are trying to update doesn’t exist. Confirm that the element exists first. I usually use the .length property or the toggle() method to make sure I have the correct reference.

And for any event issues, make sure that the DOM element exists before you bind any events to it. A related cause is when you bind an event with an element but then update the  element in thee DOM so you lose the reference. An easy solution to avoid this problem is to use something like the .delegate() method if you’re using jQuery.

To sum it up, whenever you run into a problem carry out the following steps.

1. Isolate the problem

2. Focus on the problem area

3. Fix the bug (easy part!)