Managing Mobile and Non-mobile Versions of a Site Using Tera-WURFL and Zend Framework

Posted in Mobile, PHP, Programming and Zend Framework on Tuesday, the 12th of February, 2008.

This is a quick proof-of-concept I put together after a discussion on how to deal with running a mobile site and a 'full' web site on the same hostname in a sane way, and to transparently route user agents to the appropriate site.

Steps Involved

i) Organise the 'Web' and 'Mobile' sites as separate Modules in Zend Framework

This way, any users accessing URLs beginning /mobile (or whichever path we nominate) will automatically be routed to the controllers in the Mobile module and users accessing URLs beginning /web will be routed into the Web module.

ii) Add a 'Default' Module

Users will be routed to this if they access any other path, such as / or /ringtones

The configuration for this in the bootstrap looks a little like this:

<?php

$frontController
->setControllerDirectory(array(
    
'default' => '../application/modules/default/controllers',
    
'web'     => '../application/modules/web/controllers',
    
'mobile'  => '../application/modules/mobile/controllers',
));

That tells the FrontController where to look for the right controllers.

iii) Query Tera-WURFL to identify the device

I chose to do this as a ControllerPlugin, as this will be run regardless of the user's entry URL.

<?php

require_once '/path/to/tera_wurfl/tera_wurfl.php';

class 
TwurflPlugin extends Zend_Controller_Plugin_Abstract {

    
/**
     * Only ever called once at the start of dispatch
     * @access public
     */
    
public function dispatchLoopStartup(
                         
Zend_Controller_Request_Abstract $request)
    {
        
$tw = new Tera_Wurfl();
        
$tw->getDeviceCapabilitiesFromAgent(
                        
$request->getHeader('User-Agent'));
        
Zend_Registry::set('twurfl'$tw);
    }
}

...and register that with the FrontController like so:

<?php

$frontController
->registerPlugin(new TwurflPlugin());

A nice side effect is that the Tera_Wurfl object is pulled from the database once and once only, and is thereafter available via the Zend_Registry for the lifetime of the request.

iv) Use the IndexController of the Default module to route requests into the appropriate module

<?php

class IndexController extends Zend_Controller_Action {

    
/**
     * Called automatically by ZF before a *Action()
     * method is called
     *
     * @access public
     */
    
public function init()
    {
        
$this->_helper->viewRenderer->setNoRender(TRUE);
    }
    
    
/**
     * Called by magic
     *
     * @access public
     */
    
public function __call($methodname$args)
    {
        
$tw Zend_Registry::get('twurfl');
    
        if ( 
$tw->browser_is_wap ) {
    
            
$this->_forward(
                        
$this->_request->getActionName(),
                        
$this->_request->getControllerName(),
                        
'mobile');
            
//$this->_redirect('/mobile');
    
        
} else {
    
            
$this->_forward(
                        
$this->_request->getActionName(),
                        
$this->_request->getControllerName(),
                        
'web');
        }
    }
}

Note the use of the PHP5 __call() magic method, which effectively gives us wildcarding of URLs, so we don't need to create an action method for every possible path.

Outcome

Send to:

Comments

Join the discussion! Post your comment.