Introduction to Zend_Layout (updated for ZF 1.5!)

March 17, 2008 – 6:59 pm Tags:

I wrote earlier a post about the back then new Zend_Layout component in Zend Framework. It’s one of my most popular posts, so I think it’s about time for me to write an updated version which actually works in ZF 1.5’s version of Zend_Layout.

We’ll look into how to get started with Zend_Layout, and we’ll also check out the new view helpers.

Getting started

Zend_Layout is now included with Zend Framework (since 1.5), so you will be able to start using it right away.

Let’s make one assumption before starting: we have defined a constant called APP_PATH, which contains the path to our application’s root directory. So when you see APP_PATH in the code, you’ll know what it means.

First, in our bootstrap, we need to initialize Zend_Layout (ZL from here on):

Zend_Layout::startMvc(array(
    'layoutPath' => APP_PATH . '/application/layouts'
));
 
//Let's assign our imaginary base url in the view so we can refer to it:
$view = Zend_Layout::getMvcInstance()->getView();
$view->baseUrl = '/baseurl';

The startMvc command registers ZL’s plugins and such and we can use it to define settings, like the layout path. Since we defined that our layouts reside in application/layouts, we need to create that dir if it does not exist. Assigning the base URL is not absolutely necessary, but it can provide useful if you need to refer to files, such as CSS or JavaScript, in your views and we’ll be using it later in this article.

Next, let’s create the default layout:

application/layouts/layout.phtml

<html>
 <head>
  <title>Layout example</title>
 </head>
 <body>
 
  <?= $this->layout()->content; ?>
 
 </body>
</html>

The above creates a simple HTML page. The PHP code snippet there displays the data rendered in your actions. It is essentially a view script, so you can use view helpers and such in it.

This is all we need. You now have a working Zend_Layout enabled site! Just add controllers and the other usual stuff. By default, Zend_Layout will include the contents rendered by the view in your actions in the content variable shown in the above layout code, so you will not have to do anything special to get your views rendered inside the layout.

Zend_Layout view helpers

There’s a couple of new view helpers that help us with various tasks related to layouts.

The doctype and head helpers

Let’s modify our layout.phtml a bit:

<?= $this->doctype(Zend_View_Helper_Doctype::XHTML1_TRANSITIONAL); ?>
<html>
 <head>
  <?= $this->headTitle('Layout example'); ?>
  <?= $this->headLink()->appendStylesheet($this->baseUrl.'/css/example.css'); ?>
  <?= $this->headScript(); ?>
 </head>
 <body>
 
  <?= $this->layout()->content; ?>
 
 </body>
</html>

We can see some helpers in action there. The doctype, headTitle, headLink and headScript helpers.

The doctype helper is used to render the DOCTYPE tag, which is quite nice as I can’t ever remember its syntax! You simply pass one of the constants of Zend_View_Helper_Doctype to it as a parameter.

The head helpers are a bit more advanced. Their job is to render various elements you see in the head tag, such as the title, link elements for CSS and script elements for JavaScript.

Why are they needed instead of just using HTML? For example, if you have a specific action, which requires some JavaScript code. You probably would not want to include the JavaScript code on pages where it is not needed, because it would make your pages bigger and slow down loading etc., so you can simply use the headScript helper:

A view script for myAction in MyController

<?php 
//Let's add some JS and CSS and change the title:
$this->headScript()->appendFile($this->baseUrl . '/js/something.js'); 
$this->headLink()->appendStylesheet($this->baseUrl . '/css/new.css');
$this->headTitle(' myAction MyController');
?>
<h1>Bla bla</h1>
Some HTML etc. here.

Now, the above code would make the layout include a JavaScript file, add another CSS file and modify the title so that in addition to “Layout example”, it says “myAction MyController”.

The partial and partialLoop helpers

partial and partialLoop can be used to render sub-views, in the same way as you would use $this->render(…) in a view script to render another view script inside it. The main difference between using render() and partials is that partials are rendered in a separate scope, meaning that you will not be able to access the view variables in the parent view from inside your partial views.

When using partials, you’ll need to pass the viariables to it:

<?= $this->partial('mypartial.phtml', array('var1' => 'hello', 'var2' => 'world')); ?>

The above would render mypartial.phtml, and assign two variables in it: var1 and var2.

Partialloop is basically the same, except it can be used to render the same partial multiple times, like the name says.

The action helper

The action helper is used to call actions from inside the views. This can be useful for various things, such as rendering content which needs to be loaded from the database, but isn’t necessarily related to the current “main” action.

Let’s modify our layout.phtml again:

<?= $this->doctype(Zend_View_Helper_Doctype::XHTML1_TRANSITIONAL); ?>
<html>
 <head>
  <?= $this->headTitle('Layout example'); ?>
  <?= $this->headLink()->appendStylesheet($this->baseUrl.'/css/example.css'); ?>
  <?= $this->headScript(); ?>
 </head>
 <body>
  <div>
   <?= $this->action('menu', 'layout', 'default'); ?>
  </div>
 
  <?= $this->layout()->content; ?>
 
 </body>
</html>

So we added a call to $this->action in the layout. It will call LayoutController’s menuAction method, in the default module. The syntax used for the parameters is the same as for _forward(), so you can also pass parameters to the action:

$this->action('action', 'controller', 'module', array('param1' => 'foo', 'param2' => 'bar'));

You can call any actions you want with the action helper. It will call it and get the rendered view and output it on the page. Note that plugins (such as Acl) will not be applied!

In closing

Now you should know enough to get going with Zend_Layout. Feel free to ask any Zend_Layout related questions in the comments!

Don’t forget to see the Zend_Layout documentation and the documentation for view helpers, as they contain more useful information you may need at some point.

  1. 15 Responses to “Introduction to Zend_Layout (updated for ZF 1.5!)”

  2. I’d recommend calling the doctype() helper with the doctype you want from your bootstrap. The rationale is that a number of the view helpers are doctype aware — such as the form*() helpers — and defining the doctype early allows these to render correctly for the doctype you desire. Then, in your layout, you only need to call $this->doctype() to render it.

    By Matthew Weier O'Phinney on Mar 17, 2008

  3. That’s a good tip. Wouldn’t have thought about that myself.

    By Jani Hartikainen on Mar 20, 2008

  4. Hi,
    Is it possible to render a seperate layout (or a seperate view template) into a variable after its rendered with the smarty class? (with help from your smartyview and smartyviewadvanced class)

    By Pluto on Mar 24, 2008

  5. How does one go about setting the layout path when they are using modules? I.E.

    modules/
    - admin/
    —- views/
    ——-layouts/
    - default/
    —- views/
    ——-layouts/

    Is there any way to configure Zend so that it includes the correct layout file depending on the module being used.

    Zend_Layout::startMvc(array(’layoutPath’ => ‘../application/modules/:module/views/layouts’));

    where the :module variable would be the current module in quesiton

    By Hayden on Mar 30, 2008

  6. Hayden: the assumption with Zend_Layout is that all layout scripts are kept in a common directory, regardless of module.

    That said, it’s trivial to switch the layout directory — and layout script — from a given controller or view script — both action and view helpers exist for the layout object.

    You can also easily extend Zend_Layout to add the functionality you desire. If you feel it’s a common enough pattern, please propose it on the mailing lists.

    By Matthew Weier O'Phinney on Mar 30, 2008

  7. Hi Matthew,

    Nice introduction to Zend_Layout.

    A detail that bothers me is that the string from the $this->headTitle() located in the view script is not added at the end of the one from the layout $this->headTitle() but at its beginning… or did I do something wrong??

    By A developpeur in Paris on Apr 12, 2008

  8. To the developpeur in Paris:

    I noticed that the title is appended as well. To fix that, I did:

    headTitle(’Layout example’, ‘PREPEND’); ?>

    within layout.phtml

    By edtechre on Apr 23, 2008

  9. Hi,

    I have this in my bootstrap file:

    some code …

    $frontController = Zend_Controller_Front::getInstance();
    $frontController->throwExceptions(true);
    $frontController->setControllerDirectory(array(’default’=>’../application/default/controllers’,'admin’=>’../application/admin/controllers’));
    Zend_Layout::startMvc(array(’layoutPath’=>’../application/layouts’));
    $frontController->dispatch();

    All is good if I access my action script in ‘default’ path, like this http://project/index and index controller with index action is run, but if I try http://project/admin/ I am getting ‘Invalid controller specified (index)’ because it still looks into ‘defaul’ path for admin controller… Is anybody knows how to access ‘admin’ controllers?
    My layout:
    /aplication
    admin/
    controllers/
    views/
    scripts/
    same for ‘default’
    layouts/
    models/
    /lib
    /public

    Any help please?

    Thanks
    Alex

    By alex on May 1, 2008

  10. Alex,

    Try using $frontController->setModuleDirectory(’../application/modules’) and put your admin/ and default/ dirs under there. I’d say that is a better approach, as you won’t have to edit the bootstrap every time you add a new module.

    By Jani Hartikainen on May 1, 2008

  11. Hi,
    Now I am getting this:
    ‘Zend_Controller_Exception’ with message ‘No default module defined for this application’
    I have this lines in bootstrap (index.php)
    $frontController->setModuleControllerDirectoryName(’../application/modules’);
    $frontController->setDefaultModule(’default’);

    The $frontController->setModuleDirectory(’../application/modules’)
    gives error - undefined property setModuleDirectory

    Can you please help, I am beginner with ZF
    Thanks
    Alex

    By alex on May 2, 2008

  12. Yeah the correct method would be addModuleDirectory, not setModuleDirectory. I just remembered it wrong. =)

    Anyways, I would suggest you check out the ZF manual ’cause it’s said there too, and you might get an answer faster that way.

    By Jani Hartikainen on May 2, 2008

  13. Hi,
    I have found the answer to my question. The set-up is working, problem was in naming objects (classes). For example: if you have controller in admin/controllers module, you still need to create ActionController.php BUT your class name must be prefixed like this admin_ActionController, other wise Zend won’t find it. I hope this will help somebody else as well.

    Thanks
    Alex

    By alex on May 6, 2008

  1. 3 Trackback(s)

  2. Mar 17, 2008: Quick introduction to using Zend_Layout | CodeUtopia
  3. Mar 31, 2008: Templates - Zend Framework Forum
  4. Apr 21, 2008: Zend Framework 1.5 Praise, and Free Skeleton App Download | Joey Adams Dot Net

Post a Comment