Federico Cargnelutti

Simple is better than complex. Complex is better than complicated. | @fedecarg

Adding theme support to your Zend Framework application

with 18 comments

This is a brief explanation on how to add theme support to your Zend Framework application and how to ensure those themes are self-contained, easy to distribute and install.

Themes are very powerful and extremely easy to develop. They allow you to quickly switch between layouts and change the look and feel of your application. You can use themes to show, for example, a mobile friendly version of your site.

Making a Zend Framework application theme-able is a three-step process.

First, modify your directory structure:

application/
    controllers/
library/
public/
    themes/
        default/
            css/
            images/
            templates/
        custom/
            css/
            images/
            templates/

Then, edit your Bootstrap class:

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initView()
    {
        $theme = 'default';
        if (isset($this->config->app->theme)) {
            $theme = $this->config->app->theme;
        }
        $path = PUBLIC_PATH.'/themes/'.$theme.'/templates';

        $layout = Zend_Layout::startMvc()
            ->setLayout('layout')
            ->setLayoutPath($path)
            ->setContentKey('content');

        $view = new Zend_View();
        $view->setBasePath($path);
        $view->setScriptPath($path);

        return $view;
    }
}

And finally, copy your view scripts and layouts to the templates directory:

application/
library/
public/
    themes/
        full-site/
            css/
            images/
            templates/
                error/
                index/
                partials/
                layout.phtml
        mobile-site/
            css/
            images/
            templates/

Voila, mission accomplished.


Written by Federico

September 20, 2009 at 10:43 pm

Posted in Frameworks, Open-source, PHP

18 Responses

Subscribe to comments with RSS.

  1. Nice approach.

    I’m not so keen on having anything other than images/css/js in the public directory though. Might be better to move the templates themselves somewhere else. Not quite so neat but more secure.

    Tom Graham

    September 21, 2009 at 3:10 pm

  2. Well, the example above assumes that:

    - You are using the Front Controller pattern and that all your requests are routed to a single file.
    - You have control over your server.
    - You Web server doesn’t have any rules matching phtml files.

    Why do you think this way is less secure?

    Federico

    September 21, 2009 at 3:44 pm

  3. Fair point, however in most example .htaccess files for Zend Framework the following rule exists:

    RewriteCond %{REQUEST_FILENAME} !-f

    Ofcourse it’s up to the developer to prevent access to those .phtml files :)

    Tom Graham

    September 21, 2009 at 3:54 pm

  4. True, thanks for pointing that out :)

    Federico

    September 21, 2009 at 4:56 pm

  5. [...] his blog today Federico Cargnelutti has posted an easy way you can add theme support (self-contained site templates) to your Zend Framework application. [...]

    Webs Developer

    September 21, 2009 at 7:01 pm

  6. Ideally you would just create several layouts or themes as you call them and then switch layouts in the action controller:

    $this->_helper->layout()->setLayout(‘theme_name’);

    ...

    September 22, 2009 at 12:39 am

  7. Not really. A Layout is not a theme, and a theme can have multiple Layouts.

    Federico

    September 22, 2009 at 6:25 am

  8. I kind of agree with the first comment, I would typically put the templates somewhere in my “/application” directory.
    Infact, am currently developing an application where i have my themes at “application/default/layout”, which makes me disagree with your last comment. I believe a layout is a theme, multiple layouts means multiple themes but a theme can have multiple styles (which are defined in the css).

    MayorBrain

    October 22, 2009 at 11:23 am

  9. How do you build an app for different devices then (eg. PC, iPhone or Blackberry), you don’t use multiple layouts, internal style sheets and inline styles? What’s your secret? ;)

    Federico

    October 22, 2009 at 2:45 pm

  10. (the last try…)

    To protect .phtml files add this to the .htaccess:

    <Files ~ "\.(ini|txt|phtml)$">
    Order allow,deny
    Deny from all
    </Files>

    typografia

    November 6, 2009 at 12:58 pm

  11. Your code examples are a bit confusing. Your structure deviates from public/theme/default to be public/theme/full-site public/theme/mobile-site

    Andre Ferreira

    January 21, 2010 at 7:43 pm

  12. Default site = Full site
    Custom site = Mobile site

    Federico

    February 8, 2010 at 10:18 am

  13. This does not work so well if you are using the conventional modular structure.

    Greg

    April 1, 2010 at 6:57 pm

  14. Federico — This is a great idea. Some commenters above are confused about the definition of a theme. If you define a theme as the presentation layer (layouts, view scripts, css, js) your method is great. I also don’t see security risks inherent to this approach – like it was stated above, it’s up to the server admin to manage file access appropriately. Thanks for sharing your insights.

    Martin Rio

    May 2, 2010 at 2:13 am

  15. Hi,

    i’m wondering where you get the $baseDir?

    i’m getting errors

    Fatal error: Uncaught exception ‘Zend_View_Exception’ with message ‘script ‘error/error.phtml’ not found in path (computer_path/application/views\scripts/)’

    Any ideas?

    thx,

    James

    James

    August 26, 2010 at 10:07 am

  16. Fixed

    Federico

    August 26, 2010 at 10:37 am

  17. Hey,

    thx for the quick response, but it is still not working?

    $view->setScriptPath(‘/path/to/script’);
    $view->setScriptPath(‘../public/themes/’.$theme.’/templates’;');

    Still looking for the files in the views/scripts folder?

    Anyone knows the correct path?

    thx,

    james

    James

    August 26, 2010 at 12:27 pm

  18. Make sure to pass the same value to $layout->setLayoutPath() and $view->setScriptPath()

    Federico

    August 26, 2010 at 10:19 pm


Leave a Reply