Creating a separate mobile layout for a Zend Framework application

I've got a Pre… and Sprint.  Together they make for a pretty poor browsing experience.  More due to the Sprint part I presume since browsing the web is a painfully slow experience.  The Pre has other problems.  That poor browsing experience has extended to the e_eschrade website for me even though there aren't a lot of elements that need to be loaded.  So to get around that I decided that it was time to make my site (mostly) mobile friendly.

Doing that was actually relatively easy.  It isn't perfect since it doesn't automatically know ANY type of mobile phone but I think I have it covered so that many mobile devices can be found.

The way I did it was simply by adding yet another Zend Controller plugin called Esc_Application_Plugin_Mobile and enabled it in my application config by adding the following line.

resources.frontController.plugins[] = "Esc_Application_Plugin_Mobile"

From there I coded it.  Like I said, it's not perfect, and it might not even be pretty, but it kind of works.

class Esc_Application_Plugin_Mobile extends Zend_Controller_Plugin_Abstract
{
    private $_agents = array(
        'mobile'    => array('ipad'),
        'webos'        => false
    );
    
    public function dispatchLoopStartup(Zend_Controller_Request_Abstract $req)
    {
        $uAgent = $req->HTTP_USER_AGENT;
        foreach ($this->_agents as $agent => $negation) {
            if (stripos($uAgent, $agent) !== false) {
                if ($negation) {
                    foreach ($negation as $neg) {
                        if (stripos($uAgent, $agent) !== false) {
                            return;
                        }
                    }
                }
                Zend_Layout::getMvcInstance()->setLayout('mobile');
                return;
            }
        }
    } 
}

What this does is prior to actually dispatching the request it gets the browser user agent and iterates over all the user agents it is designed to catch.  I found based off of a Wikipedia entry on mobile user agents that a great many of them have the word "mobile" in their string.  And since I have a Pre I needed to include the Webos as a string to search for as well.  But there's a bit of a problem and that is that the iPad also has the word "mobile" in it, but it probably has a big enough screen to render the full web site.  So what I did was have it iterate over the agents, but then have an option to negate the finding.  So, in this example, if it finds the word "mobile" it will then look for the word "ipad".  If it can't find it then it sets the layout as mobile.

This, then, is the beauty of the 2-stage view pattern.  All I need to do is create a new layout called "mobile.phtml" and place it in my views/layouts directory and if someone visits the site with a mobile phone it will still print out the content as if it had been requested normally, but will skin it with a much more lightweight skin with less HTML and many fewer images.

As I said, it's not perfect, but it seems to work OK.

Related posts

13 thoughts on “Creating a separate mobile layout for a Zend Framework application

  1. Bene

    Hi,

    i was searching for a simple way to achieve a mobile layout without using a theme.

    trying your plugin mechanism i am running into the follwoing error:

    Fatal error: Call to a member function setLayout() on a non-object

    the error is produced by the line:

    Zend_Layout::getMvcInstance()-setLayout(‘mobile’);

    can u give me a hint?

  2. Bene

    sorry for spaming but your bitcheck throws error (and doesnot refresh the site) although i checked the right answer

  3. Bene

    solved it.

    finally found a little mistake in your posted code:

    foreach ($negation as $neg) {
    if (stripos($uAgent, $agent) !== false) {
    return;
    }
    }

    should be:

    foreach ($negation as $neg) {
    if (stripos($uAgent, $neg) !== false) {
    return;
    }
    }

    have fun

  4. Mark

    Actually,I think you haven’t fixed your problem. You are missing a ” character.

    “Zend_Layout::getMvcInstance()-setLayout(‘mobile’);”
    should read

    Zend_Layout::getMvcInstance()-setLayout(‘mobile’);

    Cheers

    Mark

  5. mohamed

    Actually, I think the character you’re mentioning has been stripped automatically as you can see in your own comment,
    anyway I think you should update your code to correct it as in Bene’s code.

    Cheers 😉

  6. Hi,
    The Above mention code is helpful, but still i am getting some bugs.

    resources.frontController.plugins[] = “Esc_Application_Plugin_Mobile”

    using the above line displaying nothing,

    can u provide me some video tutorial link or detailed document to handle it.

    thanks
    Firoj

  7. Kevin Schroeder

    Firoj, check your PHP error log, or turn display_errors on. I’d be willing to bet that there is a problem with your autoloader configuration.

  8. Shaik Asif

    Hai
    i like ur plugin,want to try this,but i want the structure of the folder where i have to write plugin and also where i have to initialize this plugin.simply say that i want to run this plugin so what i have to do.plz post step by step process to work in the project.

    Thank u,
    Asif

  9. Shaik Asif

    hai kevin,
    iam waiting for u reply,just explain the process of ur plugin.its very helpfull to me if u send me detail documentation of ur plugin.And the folder structure where the plugin be placed.Its very urgent iam working on this related application.
    I already tried ur plugin,But iam getting some errors(APPLICATION ERROR).
    Eagerly waiting for ur reply,
    Thank u
    Asif

  10. […] for your ZF application, you can do it by changing the layout in custom a controller plugin. The article written by Kevin Schroeder describes how to do […]

  11. good idea. let’s push it to the next level.
    How about having a mobile version for the actions views as well

    1. Kevin Schroeder

      You probably could, but I think that one of the points of having a two stage view renderer is to have the action view have what you need, but no more, and have CSS change the look for the different devices and then skin it using different layouts for different devices.

    2. florinserbu

      I have managed to get it the the view level, and have the views rendered complete different depending what device you are using with Zend contextSwitch. I explained it here http://florinserbu.wordpress.com/2012/12/11/contextswitching-on-using-zend-for-mobile-websites/

Leave a Comment