CakePHP website mobile version

19,446

Solution 1

I've done this using a quick addition to the beforeFilter() in my app_controller.php file.

function beforeFilter() {
     if ($this->RequestHandler->isMobile()) {
        $this->is_mobile = true;
        $this->set('is_mobile', true );
        $this->autoRender = false;
     }
}

This uses the CakePHP RequestHandler to sense if it's a mobile device visiting my site. It sets a property and view variable to allow actions an views to adjust themselves based on the new layout. Also turns off the autoRender because we'll take care of that in an afterFilter.

In the afterFilter() it looks for and uses a mobile view file if one exists. Mobile versions are stored in a 'mobile' folder inside the controller's view folder and are named exactly the same as the normal non-mobile versions. (ie. add.ctp becomes mobile/add.ctp)

    function afterFilter() {
        // if in mobile mode, check for a valid view and use it
        if (isset($this->is_mobile) && $this->is_mobile) {
            $view_file = new File( VIEWS . $this->name . DS . 'mobile/' . $this->action . '.ctp' );
            $this->render($this->action, 'mobile', ($view_file->exists()?'mobile/':'').$this->action);
        }
     }

Solution 2

You can use Theme feature in CakePHP 2.x for mobile layout.

Simply do:

if($this->RequestHandler->isMobile())
    $this->theme = 'mobile';

I found this better, as you can share View file on mobile and desktop theme easily.

Solution 3

Dan's answer worked for me. However, I used file_exists instead of the File constructor and added the ability to use mobile layouts. The before filter was the same, but the afterFilter looked like this:

function afterFilter() {
    // if in mobile mode, check for a valid view and use it
    if (isset($this->is_mobile) && $this->is_mobile) {
        $view_file = file_exists( VIEWS . $this->name . DS . 'mobile/' . $this->action . '.ctp' );
        $layout_file = file_exists( LAYOUTS . 'mobile/' . $this->layout . '.ctp' );

        $this->render($this->action, ($layout_file?'mobile/':'').$this->layout, ($view_file?'mobile/':'').$this->action);
    }
 }

Solution 4

I modified this technique for a CakePHP 2.1 app. Here is my beforeFilter():

public function beforeFilter() {

if ($this->request->isMobile()){
    $this->is_mobile = true;
        $this->set('is_mobile', true );
        $this->autoRender = false;
}

}

And here is my afterFilter():

function afterFilter() {
    // if in mobile mode, check for a valid view and use it
    if (isset($this->is_mobile) && $this->is_mobile) {
        $view_file = file_exists( 'Views' . $this->name . DS . 'mobile/' . $this->action . '.ctp' );
        $layout_file = file_exists( 'Layouts' . 'mobile/' . $this->layout . '.ctp' );
        if($view_file || $layout_file){
            $this->render($this->action, ($layout_file?'mobile/':'').$this->layout, ($view_file?'mobile/':'').$this->action);
        }
    }
 }

This helps account for deprecated verbiage and constants in CakePHP 2.

Solution 5

The simple solution is to create a new 'mobile' layout with respective stylesheet(s) and turn it on in AppController:

public $components = array('RequestHandler');
public function beforeRender() {
    parent::beforeRender();
    if ($this->RequestHandler->isMobile()) {
        $this->layout = 'mobile';
    }
}

It is important to do that in beforeRender() in case if you change $this->layout in your controllers' methods.

Share:
19,446

Related videos on Youtube

Nicolas
Author by

Nicolas

Updated on August 12, 2020

Comments

  • Nicolas
    Nicolas over 3 years

    I have developed a full website with CakePHP framework and we'd like to make a very light version of the website for mobile devices (mainly iPhone/iPad).

    Is there a way to use the existing website with a new sub domain (for instance mobile.mywebsite.com) which will render specific views? I would like to avoid copying and simplifying the current one to match the new one requirements. I do not want to have to "re-develop" a new CakePHP website and do the changes twice every time I need to change a controller action.

  • Nicolas
    Nicolas over 13 years
    Hi mcabral, thank you for your suggestion. I really like the idea of a sub domain because people could then switch to the full site if they want. Any idea on this feature? Have you ever used it? Cheers,
  • mcabral
    mcabral over 13 years
    @Nicolas yes, i have tried it with Zend Framework. It's a fine tool.
  • Nicolas
    Nicolas over 13 years
    Hi Dan, do you think it would be possible use your solution with a sub-domain and then let the users run the full website via a link if he wants to? Cheers,
  • Dan Berlyoung
    Dan Berlyoung over 13 years
    Possibly. My solution autosenses which device is browsing. Maybe just add a link that sets a cookie to override the browser sensing. Then no subdomain is necessary. Just a 'view full site' link that sets the cookie.
  • Nicolas
    Nicolas over 13 years
    The cookie could be a good idea indeed. I'll think about it this weekend, but it is most likely that your easy to configure solution will have my vote. Cheers,
  • Nicolas
    Nicolas over 13 years
    So I'm back, just to tell you I choose your option. I just needed to add a meta "viewport" in order to make the same layout on all mobile devices. Thanks! Nicolas.
  • Bear
    Bear almost 12 years
    Excellent solution, when I first looked into this I thought it might be very difficult, your solution is great. Many thanks.
  • happyhardik
    happyhardik almost 12 years
    In CakePHP 1.3 on a linux server you may want to add strtolower($this->name) as the Controller name will have first letter captial, causing file not found on a linux server as its case sensitive.
  • Dave
    Dave over 11 years
    Instead of if(isset($this->is_mobile && $this->is_mobile), could we just do if(!empty($this->_is_mobile)) ?
  • Dave
    Dave over 11 years
    Instead of if(isset($this->is_mobile && $this->is_mobile), could we just do if(!empty($this->_is_mobile)) ?
  • Dan Berlyoung
    Dan Berlyoung over 11 years
    The $this->is_mobile value isn't set in the beforeFilter if it is not a mobile device. The isset($x) && $x pattern tolerates this value not existing and exits gracefully. Otherwise it would generate a warning.
  • deewilcox
    deewilcox over 11 years
    @bancer's technique works well for CakePHP 2.1, too, if you have one mobile layout that can handle all of the pages on your site.
  • chronon
    chronon about 11 years
    I like the theme approach as well. One change though, it would be better to use CakeRequest instead of the RequestHandlerComponent. if ($this->request->is('mobile')) {...
  • styks
    styks about 11 years
    In cake 2.x this would be $this->RequestHandler->is('mobile')
  • trante
    trante about 11 years
    Thank you Chris for answer. Most of the customers look for a m.example.com style subdomain. Do you have any suggestions to integrate your solution with subdomain usage?
  • Sabeeh Chaudhry
    Sabeeh Chaudhry almost 11 years
    One thing which I would to like add in this solution, here $this->name is being used, for getting controller name, this works fine when there is no underscore in controller name in URL, in case of underscore this will cause error, so better $this->params['controller'] should be used, hence $view_file = new File( VIEWS . $this->params['controller'] . DS . 'mobile/' . $this->action . '.ctp' ); should be used for safety.
  • artSir
    artSir about 9 years
    This one is the easiest one for me to implement - 5/20/15
  • bowlerae
    bowlerae about 9 years
    One thing neither of these answers address is the fact that if you are rendering a different view from your controller via $this->render(), then the view of the action is displayed as opposed to the other view you have specifically called.