Tutorials

An Example Zend Framework Blog Application – Part 4: Setting the Design Stage with Blueprint CSS Framework and Zend_Layout

Oct 02, 2008 insic 16 Comments

Step 1: Adding Blueprint to the Project

You can download the Blueprint CSS framework from http://code.google.com/p/blueprintcss/. It is released under a dual licensing system using a Modified MIT License, or the GNU General Public License. Decompress the archive of the latest 0.7 release (as at time of writing) and return to our current project’s public directory.

Inside public create a new directory called css. Into this new directory, copy the decompressed blueprint directory and LICENSE file from the Blueprint distribution. We retain the license so future redistributions of the project (if any) include a copy for reference.

Blueprint contains a default set of reasonable styling. This include the most fantastic of them all – when included correctly into any HTML document it sets all browsers to the same set of defaults. This completely negates the usual pain of Firefox, IE6, IE7 and Safari having sufficiently different styles internally that designs need a ton of small browser specific adjustments by hand. By hand is evil – Blueprint does it without interference.

To complete this step, create an empty CSS file called style.css inside the /public/css directory. We’ll include this in our HTML as a point for customising the Blueprint CSS and adding additional styling as needed.

Step 2: Creating a Test HTML Document applying Blueprint CSS

The first step to any good design is using Photoshop or gimp to draw one up. I’m really bad at that however – so I stick with lots of filler text and write plain HTML from the start. Besides, it’s a blog page – how complex can it be? ;-) Famous last words…

We already have a “Hello, World” page from Part 3 of this article series – so let’s stick with what we have and throw in a bunch of HTML for a potential main blog index page. We’ll use lot’s of words like “lorem ipsum” in keeping with a long history (“lorem ipsum” is the start of a long block of text used as filler text in printers since the 1500′s – the full traditionally used text itself is over 2000 years old!)

A quick word on using Blueprint CSS. Blueprint assumes you can’t align divs (in this case not far from the truth :-)) so they use a handy grid based system. Each page is divided into a number of fixed width grids. If you know the proportions, you can give columns a grid-width and then never look at anything in a CSS file using the term “float” again. Here I assume a page has 24 fixed length columns. Main text from blog entries will be displayed within columns 1-16. I’ll have a column for non-entry content spanning 7 columns to the right. Headers and footers will take up the full page width of 24 columns.

Starting simple, open up the /application/views/scripts/index/index/phtml template used by our default Index controller and edit to contain the following:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN”
  “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>
<html xmlns=“http://www.w3.org/1999/xhtml” xml:lang=“en” lang=“en”>
<head>
    <meta http-equiv=“Content-Type” content=“text/html; charset=utf-8″ />
    <meta name=“language” content=“en” />
    <title><?php echo $this->escape($this->title) ?></title>
    <link rel=“stylesheet” href=“/css/blueprint/screen.css” type=“text/css” media=“screen, projection”>
    <link rel=“stylesheet” href=“/css/style.css” type=“text/css” media=“screen, projection”>
    <link rel=“stylesheet” href=“/css/blueprint/print.css” type=“text/css” media=“print”>
    <!–[if IE]><link rel=“stylesheet” href=“/css/blueprint/ie.css” type=“text/css” media=“screen, projection”><![endif]–>
</head>
<body>
   
    <div class=“container”>

        <div class=“block”>
            <div id=“zfHeader” class=“column span-24″>
                <h1>Lorem Ipsum</h1>
            </div>
        </div>

        <div class=“block”>
            <div id=“zfContent” class=“column span-16″>
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            </div>

            <div id=“zfExtraRight” class=“column span-7″>
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            </div>
        </div>

        <div class=“block”>
            <div id=“zfFooter” class=“span-24″>
                <p>Copyright &copy; 2008 Pádraic Brady</p>
            </div>
        </div>

    </div>

</body>
</html>

Go ahead and reopen http://zfblog/ in a browser. You’ll quickly notice that with little effort, it looks oddly pretty and the main content and right column are aligned exactly even.

In the HTML we did some very simple things. We have the standard 3 block solution – Header, Content, Footer. Both are contained in div’s with assigned “span” width. Content is further divided into two columns with “span” widths – the total of which add to 1 less than the total of 24 spans. The reason for the missing span is simply to allow room for further styling which in varying browsers can have knock on effects – typically using the full span wodth across multiple column blocks ends up with a browser breaching the fixed 24 width and leaving a column dropped below the others.

Let’s add a few modifications to allow for a more realistic appearance of blog entries with a title and other assembled summary data.

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN”
  “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>
<html xmlns=“http://www.w3.org/1999/xhtml” xml:lang=“en” lang=“en”>
<head>
    <meta http-equiv=“Content-Type” content=“text/html; charset=utf-8″ />
    <meta name=“language” content=“en” />
    <title><?php echo $this->escape($this->title) ?></title>
    <link rel=“stylesheet” href=“/css/blueprint/screen.css” type=“text/css” media=“screen, projection”>
    <link rel=“stylesheet” href=“/css/style.css” type=“text/css” media=“screen, projection”>
    <link rel=“stylesheet” href=“/css/blueprint/print.css” type=“text/css” media=“print”>
    <!–[if IE]><link rel=“stylesheet” href=“/css/blueprint/ie.css” type=“text/css” media=“screen, projection”><![endif]–>
</head>
<body>
   
    <div class=“container”>

        <div class=“block”>
            <div id=“zfHeader” class=“column span-24″>
                <h1>Lorem Ipsum</h1>
            </div>
        </div>

        <div class=“block”>
            <div id=“zfContent” class=“column span-16″>
               
                <h2>Excepteur Sint</h2>
                <p><?php echo gmdate(‘D, j M Y H:i:s T’, time()) ?><br />
                Posted by Pádraic Brady</p>
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
                <hr />
                <p>Tags: Lorem, Ipsum, Excepteur</p>

                <h2>Excepteur Sint</h2>
                <p><?php echo gmdate(‘D, j M Y H:i:s T’, time()) ?><br />
                Posted by Pádraic Brady</p>
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
                <hr />
                <p>Tags: Lorem, Ipsum, Excepteur</p>

            </div>

            <div id=“zfExtraRight” class=“column span-7″>
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            </div>
        </div>

        <div class=“block”>
            <div id=“zfFooter” class=“span-24″>
                <p>Copyright &copy; 2008 Pádraic Brady</p>
            </div>
        </div>

    </div>

</body>
</html>

What we now have is pretty basic – but even in black and white it looks clean and quite blog-like. If you disable CSS for your browser, well, it still looks quite fine which is always a positive thing.

Step 3: Splitting persistent markup into a Zend_Layout template

Traditionally, PHP templating has rarely addressed a common problem we have using templates. Somewhere in the design above (you can spot this easily) are elements common to almost every future page of our blog application. A stock solution is often to push these elements into separate templates, and include them as needed. This poses the problem of widespread references to these templates. What happens if we decide they only apply to half our site now, and need to replace them for 50% of all existing page specific templates? I call it PAIN. Others call it MIND-NUMBING.

A simple tactic to avoid these symptoms is to segregate common elements in one single location, and make sure individual templates remain blissfully unaware of it’s existence (then those 100 templates have nothing to edit if the central common template is replace for 50 of them!).

In the Zend Framework this tactic was initially proposed over a year ago when attention was slowly turning towards the weak Zend_View side of the MVC equation. I proposed Zend_View Enhanced which include, among a lot of things, a Zend_View based solution to the common layout problem. Ralph Schindler proposed around the same time a Zend_Layout component for similar purposes. Eventually I lost on that score, and Zend_Layout was adopted. Such is life – at least the rest of Zend_View Enhanced with some modification was also adopted, making for a powerful templating solution taking full advantage of the PHP language (and not a limited subset obscured behind a secondary tag language).

Examining our design above we can spot the common bits: header, footer and the righthand column. Zend_Layout uses a separate template – the Zend Framework manual is extremely obscure about how to actually get the Layout part working (hopefully fixed soon) but it’s very simple.

Create a new file in /application/views/layouts called common.phtml. What we’ll do is copy in the above index.phtml template but delete the sections that are likely to change with different page views – namely the entries.

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN”
  “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>
<html xmlns=“http://www.w3.org/1999/xhtml” xml:lang=“en” lang=“en”>
<head>
    <meta http-equiv=“Content-Type” content=“text/html; charset=utf-8″ />
    <meta name=“language” content=“en” />
    <title><?php echo $this->escape($this->title) ?></title>
    <link rel=“stylesheet” href=“/css/blueprint/screen.css” type=“text/css” media=“screen, projection”>
    <link rel=“stylesheet” href=“/css/style.css” type=“text/css” media=“screen, projection”>
    <link rel=“stylesheet” href=“/css/blueprint/print.css” type=“text/css” media=“print”>
    <!–[if IE]><link rel=“stylesheet” href=“/css/blueprint/ie.css” type=“text/css” media=“screen, projection”><![endif]–>
</head>
<body>
   
    <div class=“container”>

        <div class=“block”>
            <div id=“zfHeader” class=“column span-24″>
                <h1>Lorem Ipsum</h1>
            </div>
        </div>

        <div class=“block”>
            <div id=“zfContent” class=“column span-16″>
               
                <?php echo $this->layout()->content ?>

            </div>

            <div id=“zfExtraRight” class=“column span-7″>
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            </div>
        </div>

        <div class=“block”>
            <div id=“zfFooter” class=“span-24″>
                <p>Copyright &copy; 2008 Pádraic Brady</p>
            </div>
        </div>

    </div>

</body>
</html>

You’ll notice I replaced the fake entries with a reference to a layout() function. Function calls on the template object instance generally are either called from the template object (an instance of Zend_View) or are references to a View Helper (a small class encapsulating reusable presentation logic – we’ll hear a lot more about these later). In this case, it refers to the Zend_View_Helper_Layout class. This class instance has a public variable $content which contains all content rendered from all preceeding templates (bear in mind Layouts are rendered last – after Action specific templates).

The process is simple. You visit a Controller and Action. That Action’s template is rendered, and saved to the Layout View Helper. The Layout is rendered last, and the pre-rendered content inserted as the Layout template defines using a call to $this->layout()->content.

With our Layout template prepared, let’s remove all those common items from our Action specific template at /application/views/scripts/index/index.phtml:

<h2>Excepteur Sint</h2>
<p><?php echo gmdate(‘D, j M Y H:i:s T’, time()) ?><br />
Posted by Pádraic Brady</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<hr />
<p>Tags: Lorem, Ipsum, Excepteur</p>

<h2>Excepteur Sint</h2>
<p><?php echo gmdate(‘D, j M Y H:i:s T’, time()) ?><br />
Posted by Pádraic Brady</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<hr />
<p>Tags: Lorem, Ipsum, Excepteur</p>

Now we’re getting somewhere interesting. The revised template, only contains the content unique to that Controller/Action combination and it’s output will be inserted into the common Layout we created – after we setup Zend_Layout!

Step 4: Setting up Zend_Layout for operation

Getting Zend_Layout working is again quite simple. We just need to make a few additions to our Bootstrap file. Specifically to the setupView() static method.

<?php

require_once ‘Zend/Loader.php’;

class Bootstrap
{

    public static $frontController = null;

    public static $root = ;
   
    public static function run()
    {
        self::setupEnvironment();
        self::prepare();
        $response = self::$frontController->dispatch();
        self::sendResponse($response);
    }
   
    public static function setupEnvironment()
    {
        error_reporting(E_ALL|E_STRICT);
        ini_set(‘display_errors’, true);
        date_default_timezone_set(‘Europe/London’);
        self::$root = dirname(dirname(<u>_FILE_</u>));
                // FILE constant should have two underscores
                // preceeding and following “FILE”
    }
   
    public static function prepare()
    {
        self::setupFrontController();
        self::setupView();
    }
   
    public static function setupFrontController()
    {
        Zend_Loader::registerAutoload();
        self::$frontController = Zend_Controller_Front::getInstance();
        self::$frontController->throwExceptions();
        self::$frontController->returnResponse(true);
        self::$frontController->setControllerDirectory(
            self::$root . ‘/application/controllers’
        );
    }
   
    public static function setupView()
    {
        $view = new Zend_View;
        $view->setEncoding(‘UTF-8′);
        $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
        Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
        Zend_Layout::startMvc(
            array(
                ‘layoutPath’ => self::$root . ‘/application/views/layouts’,
                ‘layout’ => ‘common’
            )
        );
    }
   
    public static function sendResponse(Zend_Controller_Response_Http $response)
    {
        $response->setHeader(‘Content-Type’, ‘text/html; charset=UTF-8′, true);
        $response->sendResponse();
    }
   
}

Since we’re using paths a lot, I also added a $root static property rather than repeating dirname() everywhere!

The new addition sets up Zend_Layout for use – it’s automatically integrated into our application thereafter so there’s no specific on/off switch outside the Boostrap we need worry about. We pass in a few starting options to customise Layouts. We set the path where Layouts can be found, and provide a default file name (minus the .phtml file extension) to use.

One final step, because it’s bugging me as I write this. Let’s replace the Hello, World title in our IndexController (/application/controllers/IndexController.php) with something more meaningful.

class IndexController extends Zend_Controller_Action
{
   
    public function indexAction()
    {
        $this->view->title = ‘Maugrim\’s Marvelous Blog’;
    }
   
}

Go ahead and fire up a browser pointing to http://zfblog/.

Conclusion

This series, as you can tell, is all about taking small concrete steps. In this installment we’ve added a basic design, added the Blusprint CSS Framework to our toolbox, and set the pace for future templating by eradicating repetitive template code; moving it to a discrete layout template. I see it this as the conclusion of our setup tasks. In Part 3, we had a simple Hello World example. Now we have a skeletal blog design and a Layout moving. We’re looking good!

All Contents Copyrighted to Pádraic Brady.

About the author: insic

Subscribe in my RSS Feed for more updates on Web Design and Development related articles. Follow me on twitter or drop a message to my inbox.

  • http://swapnilsarwe.phpnet.us Swapnil Sarwe

    Hey insic, actually i wanted to give feedback about ur site and few suggestions… but there is no place to do that so posting it here.

    I found your site in search of simple small codes of PHP to create my own library and got to your site, since then I am subscribed to the feed.

    1st of all previous and next article links font color makes is almost invisible to read. make it a bit darker shade if possible or whatever that suits your visualizations.

    2nd if you are getting spammed from the contact page, plz get rid of it till the time you don’t finish that work. its against webmasters ethics to have a link which you are aware – that it is not working.

    Hope to see some nice resources or content in near future. By the way plz read this comment and delete it while moderating, since this is not the correct place for this comment.
    Anyways, will be getting myself updated through feeds.

  • jamez

    hey, Nice Portfolio

  • Chris

    Hi, Your contact form is broken. I would be interested in hiring you for a very large design job. Please get back to me.

  • http://www.insicdesigns.info insic2.0

    @Swapnil Sarwe Thank you for the comments. I appreciate it.

  • http://www.insicdesigns.info insic2.0

    @Chris Its my pleasure.

  • shaun

    Thanks for the walkthrough – I’m learning a lot :)

    I’m not sure I understand the Layouts rationale though. You spoke about having chunks of code that get referenced multiple times and the pain of updating all those references – I get that bit. But as a solution it seems that you throw all the chunks of code into one file (/views/layouts/common.phtml) and then repeat it all in /admin/views/layouts/admin.phtml.

    I don’t see the saving – because now you have the same code implemented in two files. I was expecting you to break out header.phtml, footer.phtml, etc, etc and reference them in each of the layouts. Am I missing something? Or have you just ‘not got to that bit yet?

  • http://blog.insicdesigns.com insic2.0

    @shaun i understand what you mean. if you implement this, im sure your admin layout would not be look like your public layout. In this example you can see that admin and public are the same. Following along this tutorial will answer your question.

    cheers

  • Erwin

    Hi,

    I really like the tutorials. I have followed this one but when i reload my page at the end i only see the common.phtml content?

    Erwin

  • http://blog.insicdesigns.com insic2.0

    @Erwin if you follow the tutorial without missing something you must have manage to run the app. I dont really get what you mean.

    But if you try to access this http://zfblog/ for sure view your common.phtml content with the content of your /application/views/scripts/index/index.phtml inserted by this scripts $this->layout()->content you put in your common.phtml

  • Erwin

    I have set yours and min next to eachother and I don’t see any different things in the Bootstrap file.

    What u mean is that when i go to the url to view the site I only see the content of common.html.

    Before we stated editing the bootstrap it worked fine.

  • Erwin

    Damn I am so stupid! I added the content part in common.phtml and the normal part in index.phtml. So it was my fault.

    Goign to continue with the other parts!

  • http://blog.insicdesigns.com insic2.0

    @Erwin Glad to hear that you make it work. :)

  • Stephane

    Great post! Easy to follow.

  • iop974

    Thanks for the post
    First excuse me for my bad english i’m french

    But I’ve got a problem with CSS in IE
    writing in bloc zfContent in IE is very BIG

  • http://mrakodol.info Stojan

    Nice tutorial.
    I have one problem. When I change Bootstrap file and layout, finish this part(4) of this tutorial, when I open in web browser http://zfblog/ , web browser show me a empty web page. He show noting!
    Can anybody help me?

  • http://mrakodol.info Stojan

    It tutorial is great, but I have some problem.
    I follow this tutorial and when I change Bootstrap file and visit http://zfblog/ with IE he shows noting.
    Can anybody help me?