PHP Zend Framework Hello World Tutorial under Apache + Linux

Submitted by nigel on Monday 9th August 2010

The following tutorial shows the steps involved in creating a simple Hello World example for the free PHP Zend Framework using Apache server on a Linux openSUSE platform. I am assuming here you are familiar with the concept of the Model-View-Controller (MVC) - if not, click on the link and do some mugging up on Wikipedia.

Firstly, we need to create the directory structure for our project. My project is going to be called api - not quite arbitrary since the project will ultimately morph into a REST web service, but for now lets settle on something less ambitious. So the directory structure will look like:

laptop4:/ # cd /srv/www/htdocs
laptop4:/srv/www/htdocs # mkdir api
laptop4:/srv/www/htdocs # mkdir api/application
laptop4:/srv/www/htdocs # mkdir api/application/controllers
laptop4:/srv/www/htdocs # mkdir api/application/models
laptop4:/srv/www/htdocs # mkdir api/application/views
laptop4:/srv/www/htdocs # mkdir api/application/views/scripts
laptop4:/srv/www/htdocs # mkdir api/application/views/scripts/index
laptop4:/srv/www/htdocs # mkdir api/library
laptop4:/srv/www/htdocs # mkdir api/public
laptop4:/srv/www/htdocs # mkdir api/public/css
laptop4:/srv/www/htdocs # mkdir api/public/img
laptop4:/srv/www/htdocs # mkdir api/public/js
laptop4:/srv/www/htdocs # chown -R wwwrun:www api
laptop4:/srv/www/htdocs #

The library directory will soon contain our Zend Framework but lets wait for a second. Next we'll edit our Apache server configuration file httpd.conf. I am running multiple websites on my development laptop so I will be using VirtualHosts. Add the following:

Alias /api /srv/www/htdocs/api
<VirtualHost *>
DocumentRoot /srv/www/htdocs/api
<Directory /srv/www/htdocs/api>
  Options -Indexes FollowSymLinks Multiviews
  AllowOverride All
  DirectoryIndex index.php 
  Order allow,deny
  Allow from all
  RewriteEngine Off
  <Location />
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule !\.(js|ico|gif|jpg|png|css)$ /index.php
You will obviously have to change all references to api to whatever you want to call your project. Next we need to reboot our Apache server so the changes take effect.
laptop4:/srv/www/htdocs # /etc/init.d/apache2 restart
Syntax OK
Shutting down httpd2 (waiting for all children to terminate) done
Starting httpd2 (prefork) done
laptop4:/srv/www/htdocs #

I like checking my work as I go along - so lets check that the Apache configuration is correct. Create a quick and nasty regular page controller version of index.php in the api document root.

print "Hello World!";

You should now be able to point a web browser at localhost/api/index.php or localhost/api. Note this is NOT MVC!! This is NOT the final solution!! This is just an interim check to see if the Apache configuration is correct.

Ok, now we need to download the latest version of the Zend Framework. I downloaded the minimal 1.10.7 zipped tarball from My browser downloads to the /tmp directory where we will unzip and untar, then copy over the library itself to the api/library directory for our development.

laptop4:/> cd /tmp
laptop4:/tmp> ls -lash Zend*
3.5M -rw-r--r-- 1 badzilla users 3.5M 2010-08-09 17:36 ZendFramework-1.10.7-minimal.tar.gz
laptop4:/tmp> tar zxf Zend*
laptop4:/tmp> cd /srv/www/htdocs/api/library
laptop4:/srv/www/htdocs/api/library> cp -R /tmp/Zend*/library/* .
laptop4:/srv/www/htdocs/api/library> ls

Now we need our MVC controller bootstrap to get things going. Unsurprisingly, it will be the index.php file. So open up the one we created before in fun, and over type the content with:



set_include_path($rdir '/library' PATH_SEPARATOR get_include_path());


    try {

$fcontroller Zend_Controller_Front::getInstance();



    } catch (
Exception $e) {
$contentType 'text/html';
header("Content-Type: $contentType; charset=utf-8");
'An unexpected error occurred:';
'<h2>Unexpected Exception: ' $e->getMessage() . '</h2><br /><pre>';

Some notes to accompany our bootstrap.

$rdir = realpath(dirname('SCRIPT_NAME')); I had some major grief here - the purpose of this code is to get the document root of the Virtual Host api but my first few stabs at it were returning the document root of the master virtual host on my machine - my Badzilla development domain. I finally stumbled upon the combination I used with the "SCRIPT_NAME" as the constant that pins Apache down to the correct virtual host.

set_include_path($rdir . '/library' . PATH_SEPARATOR . get_include_path()); Add the Zend library to the existing PHP search path.

require_once('Zend/Loader.php'); Include the Zend loader class.

Zend_Loader::loadClass('Zend_Controller_Front'); Load the front controller.

$fcontroller = Zend_Controller_Front::getInstance(); Get the singleton instance for the front controller. If you are a little shaky on Object Oriented PHP, check out

$fcontroller->throwExceptions(TRUE); We want to be able to see if something goes wrong!

$fcontroller->setParam('noErrorHandler', TRUE); But as this is simple example code, we won't be using the exception handler that comes with the Zend Framework.

$fcontroller->setControllerDirectory("$rdir/application/controllers"); Zend is not prescriptive - we can use any directory structure we want, so we'll tell it that we are sticking to convention as to where we put the controller.

$fcontroller->dispatch(); Let's rock and roll Image removed.

catch (Exception $e) No need for lengthy explanations here - display any error diagnostic.


As I said before, I love to check my work as I am progressing, so time to check out the bootstrapper. Obviously it'll throw an exception, but hey, that's what I am expecting! If we get an exception error then everything is working as it should i.e. no runtime 'compilation' errors - but double check your Apache log just in case. We can see that it is saying the controller was not found - of course not since we haven't coded it yet. So lets do it next.

The index controller needs to go in the directory we have already set up for it, so:


class IndexController extends Zend_Controller_Action {

    public function 
indexAction() {

$this->view->assign('title''Hello World!');


We need to be a little bit savvy here - the file must be called IndexController for Zend to be able to find it, the class must be IndexController and the function must be indexAction. In other words, the convention is:

function named {actionName}Action() within {ControllerName}Controller class within file {ControllerName}Controller.php

Aside from that, the function itself doesn't need to do too much - so all we are doing is assigning the title to be displayed in our template file. So lets create the template file:

<html xmlns="" lang="en" xml:lang="en">
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
    <?php echo $this->escape($this->title); ?>
    <h1><?php echo $this->escape($this->title); ?></h1>
The template file is saved with the name of the controller in the views/scripts/index directory, and with the .phtml extension - these are requirements of the ViewRenderer which is part of the Zend_Controller_Action inherited by our indexController class. You will also note that we are passing our output through $this->escape which converts special characters to HTML entities.
Zend 2

Ok - that's it - if you point your web browser to localhost/api you should now see our Hello World! text. Not too difficult at all!

Hopefully that'll give you the confidence to have a go at Zend Framework coding - nothing like as scary as you might have initially thought. Now lets move on to something a little more sophisticated, and something that actually achieves something useful (-ish) - my simple Zend REST server,

blog terms