I have been looking for a suitable framework to build my web applications on for some time now. The motivation behind the quest is of course to reap the benefits that a framework can bring to my web app development process. A framework that suits you can cut development time and add consistent structure to the application. However, a framework that you do not understand and that has poor documentation can have you pulling your hair in notime.
The framework should be intuitive to use and have extensive documentation. A broad user base would also be desirable as it tend to generate online tutorials, snippets and problem solving threads. I prefer to use the MVC-style architecture in my applications and the framework of choice should thus support this. In short these are my main requirements for the framework:
- MVC
- URL rewriting built in
- Some kind of ORM solution
- Intuitive to use (a very subjective property of course)
- Good documentation
- Internationalization and localization supported
The list could easily be extended with all sorts of fancy features like AJAX and Web Services functionalities. Although these might be important for an application I concentrate on the basics in this case. There are many frameworks today that have all the desired features listed above. The decision boils down, not surprisingly, to the intuitiveness and level of documentation of the frameworks. This said it is important to remember that the choice of framework is a very subjective matter and does not rely on any universal truths or ‘absolutely correct’ ways of doing things.
One possible framework candidate is the Zend Framework (ZF). It has some nice features besides the ones listed as requirements above. It uses the New BSD License (http://framework.zend.com/license) that is very allowing for all kinds of applications. The company behind it is no less than the PHP company itself; Zend. Having Zend as a backing force certainly lifts the profile of the framework. Businesses will appreciate the commercial support and consultation services provided by one of the biggest players in the PHP world. It is likely that the Zend Framework will have more buzz, tools and literature created around it than other similar frameworks. It seems to be a stable choice for the future.
Practical test
It looks good so far on paper, but how does it run in practice? Is it intuitive and simple enough for my liking? I will give it a test run and my findings are presented in the next section.
The work breakdown is the following:
- Install the Zend Framework
- Do necessary configurations
- Create an application
- Create a user table and a user model class
- Create login functionality
This should give me an idea about the ‘feel’ of the framework and I get to see how difficult configuration and database interaction is.
1. Install the Zend Framework
Download a copy of the library from http://framework.zend.com/download
It comes as a zip/tar.gz file that contains the framework files, demos and tests.
Next you need to create the folder structure that will host the framework and your own code. You can modify the folder names and locations if you want, but I see no need to do so here.

The document root and only publicly accessible folder will be the www-folder.
The Zend Framework files comes in directly under the library-folder.
2. Configuration
The configuration can be kept at a very minimum by setting up autoloaders and defining controller script locations in a bootstrap file. This bootstrap.php file is located in the application folder and is included by the index.php file that is the only publicly accessible PHP file, located in the www folder. A .htaccess file takes care of the URL rewriting.
www/.htaccess:
-
RewriteEngine on
-
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
www/index.php:
-
require '../application/bootstrap.php';
application/bootstrap.php:
-
-
/* Report all errors directly to the screen for simple diagnostics in the dev environment */
-
error_reporting(E_ALL | E_STRICT);
-
ini_set('display_startup_errors', 1);
-
ini_set('display_errors', 1);
-
date_default_timezone_set('Europe/Helsinki');
-
-
/* Add the Zend Framework library to the include path so that we can access the ZF classes */
-
set_include_path('../library' . PATH_SEPARATOR . get_include_path());
-
-
/* Add models directory to path */
-
set_include_path('../application/models' . PATH_SEPARATOR . get_include_path());
-
-
/* Set up autoload so we don't have to explicitely require each Zend Framework class */
-
require_once "Zend/Loader.php";
-
Zend_Loader::registerAutoload();
-
-
/* Set the singleton instance of the front controller */
-
$frontController = Zend_Controller_Front::getInstance();
-
-
/* Disable error handler so it doesn't intercept all those errors we enabled above */
-
$frontController->throwExceptions(true);
-
-
/* Point the front controller to your action controller directory */
-
$frontController->setControllerDirectory('../application/controllers');
-
-
// Plugins
-
$frontController->registerPlugin(new Zend_Controller_Plugin_ErrorHandler());
-
-
$config = new Zend_Config_Xml('/path-to/zf-demo/application/config.xml', 'production');
-
$db = Zend_Db::factory($config->database);
-
Zend_Db_Table_Abstract::setDefaultAdapter($db);
-
-
/* OK, do your stuff, front controller */
-
$frontController->dispatch();
Although we can create applications without more configurations it is likely that we need to configure for instance access to our database(s).
What I want is thus a configuration file. I chose to use the XML format along with the Zend_Config_Xml class to access it.
application/config.xml :
-
<?xml version="1.0"?>
-
<configdata>
-
<production>
-
<webhost>www.myserver.com</webhost>
-
<database>
-
<adapter>pdo_mysql</adapter>
-
<params>
-
<host>localhost</host>
-
<username>dbuser</username>
-
<password>a98w3yht9a32ht</password>
-
<dbname>demodb</dbname>
-
</params>
-
</database>
-
</production>
-
</configdata>
The XML config file is loaded by the Zend_Config_Xml class:
-
$config = new Zend_Config_Xml('/path-to/zf-demo/application/config.xml', 'production');
Configuration data is then accessible through the $config object as member variables. The database can for instance be set up like this:
-
$db = Zend_Db::factory($config->database);
3. Create an application
This one is easy. What I need is a controller class, a view directory and a view file.
The IndexController class is the default controller that is used if no other is called for. Accompanying the controller class is a view directory with the same name “index”. In the view directory you put one .phtml file for each action in the controller, keeping filename and action name the same.
application/IndexController.php:
-
/** @see Zend_Controller_Action */
-
require_once 'Zend/Controller/Action.php';
-
-
class IndexController extends Zend_Controller_Action
-
{
-
public function indexAction()
-
{
-
}
-
}
application/views/scripts/index/index.phtml:
-
Helloworld!
The IndexController’s default action (index) can be invoked by opening the www directory in a web browser. The www-directory should be set as document root for the domain you want to use. Let’s say the www dir equals http://yourdomain.com/
Then the IndexController, and index action can be called like this (all displaying “Helloworld!”)
http://yourdomain.com/
http://yourdomain.com/index
http://yourdomain.com/index/index
http://yourdomain.com/index/index/id/1234
The meaning of the URL components are thus
http://yourdomain.com/<controller name>/<action name>/<GET parameter name>/<GET parameter value>
4. Create a user table and a user model class
Ok. Now we have a functional application created with the Zend Framework. I want to add database functionality to my application and see how that is can be done with ZF. The database table I want to access looks like this:
-
CREATE TABLE `user`(`username` VARCHAR(25) NOT NULL,
-
`password`VARCHAR(50) NOT NULL,
-
`first_name` VARCHAR(25) NOT NULL,
-
`last_name` VARCHAR(25) NOT NULL,
-
PRIMARY KEY(`username`)
-
)TYPE MYISAM;
The table is loaded with one user row. The password is salted and md5 hashed.
I want to model the table with a model class. ZF has no ORM generator functionality that can generate model classes from existing database schemas. This mean I will have to create the model class by hand, luckily it is not complicated at all.
-
class User extends Zend_Db_Table_Abstract {
-
protected $_name = 'user';
-
protected $_primary = 'username';
-
}
The database access is declared in the bootstrap file as the default db access adapter.
-
$config = new Zend_Config_Xml('/path-to/zf-demo/application/config.xml', 'production');
-
$db = Zend_Db::factory($config->database);
-
Zend_Db_Table_Abstract::setDefaultAdapter($db);
Now I have created database access, a database table and a data model class. So far so good!
5. Create login functionality
Creating a login function requires a login form (view), a login action that checks credentials, and something that creates a session on successful login.
Let’s start with the view. I chose to do a simple HTML form (in index.phtml) for this example. The same could be done with the Zend_Form class.
application/views/scripts/index.phtml
-
<?php
-
echo $this->message;
-
if ($this->user) {
-
echo "<p>You are logged in as ".$this->user->first_name."<p>";
-
}
-
?>
-
<form method="post" action="">
-
<table>
-
<tr><td>Username</td><td><input type="text" name="username"></td></tr>
-
<tr><td>Password</td><td><input type="password" name="password"></td></tr>
-
<tr><td></td><td><input type="submit" value="Login"></td></tr>
-
</table>
-
</form>
Then we need to create an action that takes the username and password POST parameters and authenticates against the database. I will use ZF classes to do the authentication work. When a successful authentication is detected the entire User object for that user is retrieved using ZF database abstraction classes.
application/controllers/IndexController.php
-
/** @see Zend_Controller_Action */
-
require_once 'Zend/Controller/Action.php';</span></p>
-
class IndexController extends Zend_Controller_Action
-
{
-
private $salt = "0328t4aw9htiousnevziSHEp+9<w82h13qhwt";
-
-
public function indexAction()
-
{
-
-
$request = $this->getRequest();
-
// Check if we have a POST request
-
if ($request->isPost()) {
-
$postData = $request->getPost();
-
-
require_once 'Zend/Auth/Adapter/DbTable.php';
-
-
$password = md5($this->salt.$postData['password']);
-
-
// Configure with constructor parameters…
-
$authAdapter = new Zend_Auth_Adapter_DbTable(Zend_Db_Table_Abstract::getDefaultAdapter(),
-
'user',
-
'username',
-
'password');
-
$authAdapter->setIdentity($postData['username']);
-
$authAdapter->setCredential($password);
-
-
$auth = Zend_Auth::getInstance();
-
$result = $auth->authenticate($authAdapter);
-
if ($result->isValid()) {
-
// Success
-
$this->view->message = "Login successful";
-
$this->view->user = $this->getUser(Zend_Auth::getInstance()->getIdentity());
-
} else {
-
$this->view->message = "Login unsuccessful";
-
}
-
-
}
-
-
}
-
-
private function getUser($username) {
-
$u = new User();
-
$user = $u->find($username)->current();
-
return $user;
-
}
-
-
}
The Zend classes offers good help as we can see. Retrieving a mapped object from the database using the primary key is fairly trivial.
Then we are done with the coding!
A working demo of the application is found here. Login with demo : demo
The source code can be downloaded here and is free for all uses.
Summary and reflection
I am impressed with the documentation available at framework.zend.com. I had very little problem finding what I needed. Right away I also liked that the framework doesn’t seem to want to boss me around much
Zend’s promise “Built so you can pick and choose just the pieces you need to turbocharge your web applications…” is fulfilled in my opinion.
It is probably a very good idea to use as much of the ZF functionality as possible rather than creating your own code that does the same. I am sure ZF does it better in most cases. However, trying to learn everything about the ZF and using all tricks in your first ZF application may not be fruitful. The learning curve becomes too steep. Instead you can learn as you go over time. You will be less frustrated and more productive by taking small steps in adopting the ZF classes. I think the ZF has an advantage over many other frameworks in this respect, it does allow you to use it as much or little as you want.
I had used the Doctrine and Propel ORM frameworks before and they had code generators that could generate model classes from database schemas (and vice versa) making it easy to sync the database with the models. The ZF approach is much simpler and I had my doubts about it initially. Zend does not talk about having an ORM either so I wondered if I would be faced with much dreaded model routine coding. The ZF offers implementations of Martin Fowlers Enterprise Application Architecture patterns Table Data Gateway and Row Data Gateway. My simple test here gave me the impression that ZF’s implementations were surprisingly intuitive to use. Pending more demanding database applications…
References and further reading:
This article is heavily based upon the documentation provided by Zend.

