A Zend Framework tutorial, part four

by Naneau

In the first three parts of this tutorial I talked about designing your models and controllers. In this fourth part I’m going to take a look at views. Views are the final part of a MVC application. They contain code that will create the output of the application.

For most of you this will mean that your views will contain HTML. There are a few ways to do this. First, you could just use Zend_View. While this probably is the most ‘pure’ way to go from a Zend Framework point of view, it is not my first choice. I feel that mixing raw php and html leads to complicated templates, that may be hard to understand for template designers, who often aren’t really adept at coding.

Before the Zend Framework was thought up, there was Smarty. It’s my template engine of choice. I have written a little tutorial, that tells you how to use Smarty with the Zend Framework, if you’re interested.

Either way, in your controller actions you will have to initiate a view and assign variables to it. I have a controller base class, which all controllers extend from. The base itself extends Zend_Controller_Action. In that class I have a method called “createView” that does exactly what it describes. It builds a view and assigns some variables to it that all templates use. For a standard Zend_View based application this would look like:

1
2
3
4
5
6
7
8
9
10
11
12
13
protected function createView() {
    Zend_Loader::loadClass('Zend_View');
    //load it
   
    $view = new Zend_View();
    //create the view

    $view->somevariable = 'some value';
    $view->anothervariable = 'another value';
    //assign variables
   
    return $view;
}

Like I said, I tend to use Smarty for my templates, but you should realize that Smarty is a php4 library. There may be a few things you can’t do with Smarty in a php5 environment, although I have never really had any problems with it. For our example application of a blog, you will want to create a template for a single post. You can then assign a single Zend_Db_Table_Row to it and use it’s values. See part two of this tutorial for information about the controller methods readAction and getPost.

1
2
3
4
5
6
7
8
9
10
public function readAction() {
    if ($post = $this->getPost()) {
        $view = $this->createView();
        $view->post = $post;
        $this->getResponse()->setBody($view->render('post.tpl'));
    }
    else {
        //post not found, do something meaningful
    }
}

You’ll have to write a matching template file called post.tpl, which could look a little like this, though probably a lot more complex. Note that this file uses Smarty syntax, not Zend_View-like php.

1
2
3
4
5
6
7
8
9
<html>
    <head>
        <title>{$post->title}</title>
    </head>
    <body>
        <h1>{$post->title}</h1>
        {$post->contents}
    </body>
</html>

You will probably find that most of your templates contain the same code over and over again. For instance the start of the html, with the head, title, javascript and css, may not change for all your pages. You can get around this by using Smarty’s {include} tag in your templates and create a “head.tpl”, but there is another way. Just create a base template, called “index.tpl”, that gets an “include” variable from your controller action. It then includes the file you put in that variable, so you only have to write templates for the bits that really change from page to page.

That method has another benefit as well. If you write a __toString method for your view class, you don’t have to tell it to render index.tpl each and every time you set the body for your response.

1
2
3
4
public function __toString() {
    return $this->render($this->_defaultTemplate);
    //_defaultTemplate = 'index.tpl'
}

You can just assign the view as the body in your controllers

1
2
3
$view->post = $post;
$view->include = 'post.tpl';
$this->getResponse()->setBody($view);

That is pretty much it. With minimal amounts of code you can create a very functional application. Of course there still are some things left, like working with input from your users to create and modify posts, but I leave that to you. Using Zend_Db_Table models gives you the power to do that with ease.