Tutorials

An Example Zend Framework Blog Application – Part 3: A Simple Hello World Tutorial

Sep 30, 2008 insic 10 Comments

Zfblog tutorial part 3

Step 1: Creating A New Application
Before we jump into programming with the Zend Framework there are a few setup tasks. We need to install the Zend Framework, get a virtual domain running, and have a basic collection of directories and emtpy files created to hold our source code.

You’ll need to download the Zend Framework 1.5 (latest minor release) from http://framework.zend.com and put it somewhere on your include path. I try to minimise the number of include paths I end up having so I sometimes pick very odd places (like the PEAR directory which is usually already in the include_path) or another central library location like PEAR where I might have a dozen libraries all congregated.

A common solution found on blogs and articles is to put the framework into a “library” directory within your application directory tree. Ordinarily I don’t recommend this unless your application needs a specific version of the Zend Framework – centralising a Zend Framework location for multiple applications to access can make maintenance a bit easier.

I’ve settled on using a virtual host mainly because it’s easy to setup, and it helps avoid some of those annoying base path issues you get in your HTML when using mod_rewrite pretty urls – especially in development where, otherwise, the locahost document root becomes a mass of sub-directories upon sub-directories that end up causing base href issues so easily. Usually I open up the virtual-hosts.conf file from Apache’s conf directory and add something like:

NameVirtualHost ∗:80


DocumentRoot “/path/to/htdocs”
ServerName localhost


ServerName zfblog
DocumentRoot “/path/to/project/trunk/public”

This should result in all HTTP queries for http://zfblog/ reaching the selected document root (which is the public directory for the project containing index.php, located in our subversion’s working copy “trunk” directory). We’ll create this directory structure a little later. We usually also need to reference localhost to ensure it’s recognised as a host correctly – otherwise any localhost addresses you already have will suddenly divert to zfblog’s document root myseriously ;-).

For those of you on Windows XP or Vista, you also need to add the new virtual domain to your hosts file (usually at C:\WINNT\system32\drivers\etc\hosts). This is tricky in Vista – you will probably need to alter the file’s permissions using an Administrator account to grant the local user additional Modify privileges. Make sure to reverse the privileges after! Edit it to look this:

# Copyright (c) 1993-1999 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.

127.0.0.1 localhost
127.0.0.1 zfblog

Restart your browser and with a little luck the browser will at least give us a directory listing (once you add the document root “public” directory as shown below).

The least exciting part is the creation of a tree of directories to contain our source code. Wil Sinclair over at Zend is working on a Zend_Build component and this will one day hopefully eliminate too much of the repetition in creating these directories and default files. Until then let the monotony ensue (or keep a skeleton setup handy for copy and pasting ;-)).

Here’s a snapshot of what the Hello World example looks like in the directory view from Eclipse:

zfBlog Directory Structure

Copy this and create the same directory structure in a new directory called something like “zfblog”. Putting it all in “trunk” is optional – I’ve using subversion here which is why that directory exists. If you haven’t used Subversion before I highly recommend it – it’s simple to learn and use.

Let’s examine each of these directories briefly.

The “application” directory is where we place all the components of an application implementing the Model-View-Controller. Inside “application”, “controllers”, “models” and “views” represent respective locations of controller, model and view source code and templates. Inside “views” there is a subdivision between “filters”, “helpers”, “layouts” and “scripts”. For now, remember we put all templates rendered by the View inside “scripts”. In the screenshot, we see and index directory which will contain an “index.phtml” file, which is the view template for indexAction of an IndexController class. The others we’ll meet later.

The “modules” directory is also for controllers, models, and views, but in this case they are catagorised into multiple divisions of an application. If you think about it, an application can be broken into several parts, for example, the main application and an administration part. The administration section could be partitioned into the Admin Module so it’s not intermixed with the main application.

A Bootstrap.php file exists in the “application” directory which represents a class called “Bootstrap”. It’s purpose is to initialise the Zend Framework, adjust environment settings (for example, timezone and error_reporting level), and otherwise make application specific tweaks and additions before a HTTP request is processed. Most tutorials take an alternative view and put Bootstrap code into index.php. I strongly suggest you avoid this and use an actual class to organise the Bootstrap code – it makes it a lot easier to read if nothing else!

The “config” directory simply holds the configuration data for the application, for example, database connection details.

The “library” directory can hold a copy of the Zend Framework. Generally I avoid this since it’s fairly easy to just add the Zend Framework to the PHP include_path, but it’s still very useful if you want to change Zend Framework versions in use more flexibly. It’s also simple to manage if you use it to add an svn::external reference to the Zend Framework subversion repository.

The “public” directory holds all public files accessible by a request to the web server. This includes an index.php file, which handles all application requests by calling on the Bootstrap class, as well as any CSS, HTML, Javascript files, etc.

A note on deployment practice: generally when deploying you’d want to move the “public” directory to your web server to be internet accessible, but keep the non-public directories somewhere below the web root. Since the public index.php ends up only making a simple reference to the Bootstrap file served by including it, this means most of the application files will not be accessible by internet users. It also means that the index.php file will end up deciding where the Bootstrap file is located – so it’s the one public file that always needs to be edited by hand for deployment to change that location as needed.

The “tests” directory usually holds any application specific unit, integration and acceptance tests. As I noted previously I’m deliberately taking a test-light approach to stay on topic (I have more than one testing/development article on Zend Devzone if interested in applying TDD or BDD). Main tests I expect to have are for application specific classes: any Model logic for example.

At the end of this step you should have the directory structure in place containing some empty files as follows (create them now, and we’ll fill them in later):

/application/Bootstrap.php
/application/controller/IndexController.php
/application/views/scripts/index/index.phtml
/public/index.php
/public/.htaccess

Step 2: Implementing Our Bootstrap File
Bootstrapping is when we setup the initial environment, configuration and Zend Framework initialisation for our application. It’s not a difficult file to write, but it can grow ever larger and complex as your application gains features. To manage this I strongly suggest implementing it as a class with bitesize methods. Breaking it up does wonders for your sanity. For our Hello World skeleton application, /application/Boostrap.php contains:

<?php

require_once ‘Zend/Loader.php’;

class Bootstrap
{

    public static $frontController = null;
   
    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’);
    }
   
    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(
            dirname(__FILE__) . ‘/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);
    }
   
    public static function sendResponse(Zend_Controller_Response_Http $response)
    {
        $response->setHeader(‘Content-Type’, ‘text/html; charset=UTF-8′, true);
        $response->sendResponse();
    }

}

The Bootstrap class has two main methods here: run() and prepare(). run() executes a full application request, whereas prepare() only sets up (but doesn’t execute) the Front Controller. For now let’s focus on run() and all the steps our Bootstrap takes when it’s called. The prepare() method is something I use when applying TDD or BDD to developing controllers, since I then delegate controller execution to the testing framework.

The first thing is to setup the local environment. So here we’ve set a timezone (as required by PHP5), enabled PHP’s display_errors option, and set a fairly stiff error reporting level. If putting these basics into a class seems counter intuitive, you can simply extract them to the file head. Because I usually test extensively, I usually don’t want these running during my tests and interfering with test results.

Secondly we prepare the Front Controller. Zend_Controller_Front is an implementation of the Front Controller Design Pattern, which acts as a single point of entry into a Model-View-Controller architected application. I kid you not – every request which is not for an existing public file will go through it. In our case, since the Bootstrap is included into, and called by public/index.php, “index.php” is our single point of entry.

Here, the prepare() stage involves setting up the Front Controller:
- get an instance of Zend_Controller_Front
- set it to throw all Exceptions (might want to disable this in production)
- set it to return a Response object when dispatched
- tell it where to find the default controllers

The last step of prepare() makes some changes to the View. The reason I’ve done this is to show how to make an extremely common change – adding support for UTF-8 encoded output (such as my name!). Don’t worry too much about the details now – the ViewRenderer Action Helper and the Helper Broker lets one add or modify Action Helpers and is well covered by Matthew Weier O’Phinney over on Zend Devzone – http://devzone.zend.com/article/3350-Action-Helpers-in-Zend-Framework.

Now, what about /public/index.php?

<?php

// Update after deployment for location of non-public files
$root = dirname(dirname(<u>_FILE_</u>));

// We’re assuming the Zend Framework is already on the include_path
set_include_path(
    $root . ‘/application’ . PATH_SEPARATOR
    . $root . ‘/library’ . PATH_SEPARATOR
    . get_include_path()
);

require_once ‘Bootstrap.php’;

Bootstrap::run();

Simplicity itself! The index is our Front Controller’s single point of entry into a Zend Framework application, and all it needs to do is determine a valid include_path for the application and then delegate all other tasks to the Bootstrap class’s run() method.

The final step is how to make all requests to “http://zfblog/” pass through index.php. This is solved for Apache web servers using it’s Rewrite Module, which simply takes an incoming request URL, and rewrites it so it points to index.php. If you’ve never used Apache Rewrite before, you probably need to enable this module in http.conf before this works. Rewrite rules can be defined in Apache’s http.conf file, or simply via a .htaccess file in “public” containing the rules:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .∗ index.php

The .htaccess file here first turns on Rewriting, and then specifies rules. The rules here map all requests to index.php, unless they relate to a file which exists on the server (i.e. it won’t rewrite URLs to CSS, Javascript or image files).

Step 4: Implementing The Index Controller
Before we continue, a quick word on controller/view wiring. Some time back it was decided to make automated rendering the default mode of operation for the Zend Framework. This means Controller will rarely need manual intervention to render a View – instead an Action Helper called the ViewRenderer (which should sound familiar since it used it to add UTF-8 encoding in our Bootstrap!) is called upon. This helper locates a View matching the name of the current Controller and Action and automatically renders it. There are ways to disable this automated rendering as documented in the manual – which is often useful when you want to bypass Zend_View (e.g. maybe you’re outputting finalised JSON or XML and no further templating or processing is needed).

If a URL to a Zend Framework application does not contain a controller or action reference, then the Zend Framework uses the default “index” value. Since we only intend requesting to the root URL of “http://zfblog/”, we’ll need an Index Controller containing an Index Action. Let’s create one!

Add a file called “IndexController.php” in application/controllers containing:

<?php

class IndexController extends Zend_Controller_Action
{
   
    public function indexAction()
    {
        $this->view->title = ‘Hello, World!’;
    }
   
}

All controllers must extend Zend_Controller_Action, since it contains all later referenced internal methods and properties common to all Controllers. If you need to tweak the basic Controller to add new methods or properties you may do so using a subclass of Zend_Controller_Action and then making all application Controllers extend this subclass instead. Be very careful however in subclassing this way – it’s useful for adding new properties to the class, but additional methods are often better added as discrete Action Helpers.

Our new Action method ignores rendering; it’s done automatically as discussed earlier. All we need to do is set View data we need. You can add almost anything to a View, since it just becomes a property in a View template. So feel free to add Objects and Arrays. If using Smarty or PHPTAL, this might be different.

Above we’ve told the View that templates might refer to a variable “title” and given it a value of “Hello, World!”. Once the Action method is done, the ViewRenderer will kick in and try to render a template located at “/path/to/application/views/scripts/index/index.phtml”.

And what use is a Controller, without a View to display?

Step 5: Implementing The View For IndexController::indexAction()
By default, the Zend Framework or more specifically the ViewRenderer Action Helper, will attempt to render a View template for all Controller Actions using a simple convention. For example, the template for IndexController::indexAction() should be located at “/index/index.phtml” within the “scripts” subdirectory of “views”.

The Zend_View component is responsible for rendering all View template, often with a little assistance (e.g. ViewRenderer or Zend_Layout) from the Controller. A Zend_View template is HTML (or some other output type) interspersed with PHP and it doesn’t use a separate tag language such as what the Smarty template engine, for example, uses. Here’s something to put into your index.phtml file for our first Zend Framework application:

<!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>
</head>
<body>
    <p>Hello, World!</p>
</body>
</html>

As you can see, it’s almost pure HTML with a single PHP inclusion for the title text (which we set from our indexAction() method earlier!). To ensure security against Cross Site Scripting (XSS) we should escape all output from within the application, and Zend_View uses the PHP htmlspecialchars() function from it’s Zend_View::escape() method. Another noteworthy mention is that, since we setup our View to use UTF-8 encoding, this encoding is also passed into htmlspecialchars().

If using escape() everywhere sounds bad – well, it is, and it isn’t. It’s a pain since it’s something that would obviously benefit from automation – so not applying escaping is the exception by default. On the other hand it must be done at all times so if you ever see a variable being echoed that’s not surrounded by the escape() method you should proceed with care.

Step 6: Did it work?
Go ahead and open up your browser. The base url of http://zfblog/ should now do it’s thing and return a HTML document containing “Hello, World!”.

Conclusion
Getting a simple example up and running has already provided a few insights. But don’t let your guard down just yet. Like any battle plan, it will not survive first contact with the enemy (Maugrim’s Marvellous Blog is so evil ;-)). As we proceed, there will more than likely be a few flaws to the simple approach, our Bootstrap will need to expand yet remain maintainable, and we haven’t even looked at Zend_Db yet!

It’s a start. If you’re lucky, it may be many starts since you can reuse a similar basic skeleton to skip all those setup tasks for other Zend Framework projects.

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.

  • Andrei Constantin

    Hi there.
    Sorry to be off-topic but can you please update your contacts.php?
    I’ve been trying to get in touch with you for quite some time.

    Please mail me back.

    Regards,
    Andrei C.

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

    Hi Andrei, Thanks for dropping by. Due to intense spamming. I Disable my contact page. But don’t worry im currently working on it.

  • Andrei Constantin

    I would be greatful if you can drop me an email with your contact details / where i can find u / maybe even IM id

    Thanks a bunch

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

    OK no problem. I will PM you. :)

  • http://www.codeandpixels.co.uk Pete

    Do you have the image of the directory structure? It doesn’t seem to be loading.

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

    @Pete I’m sorry I missed it during the migration. It must be loaded by now.

  • lekha

    hi
    i tried this in my system. but i got this error ”
    Fatal error: Using $this when not in object context in /var/www/Zend/Application/views/scripts/index/index.phtml on line 7″ can u please help me?

  • kapten_lufi

    hi…i tried this but I have some problem…
    if I use url zfblog/index I’ve got message Object not found!…
    Can u exlplain what a problem?

  • hopelesschild

    Hiya, thanks for this tutorial.
    getting parse error though on /public/index.php

    Parse error: syntax error, unexpected ‘<', expecting ')' in H:\xampp\htdocs\blogappV2\public\index.php on line 4

    Can you help please?

    Here is Line 4.
    $root = dirname(dirname(_FILE_));

    What is wrong with this?

    Thanks.

  • http://www.resultnepal.com Mohit

    Can you provide the download application for the sample