Site architecture based on Zend Framework

After working on the Swedish weather site for awhile I now work on my own projects again. So I have switched Codeigniter to Zend Framework again.

After a trip to Dublin I finally launched the beginning of a new social tourist Dublin guide. It is exactly the same site as both the Swedish Fuengirola guide as well as the English Fuengirola guide I launched after living there for five months. The functionality is somewhat basic as of yet but every now and then I’ll add something more.

Basing three different sites, even though they are very similar, using two different languages gives me the possibility to try out several parts of Zend Framework. It also requires a good design both in the backend and frontend to keep it maintainable. I thought maybe some people would be interested in a basic overview of the different parts needed to put everything together.


The sites aren’t really that complicated. On a basic level there is a MySQL database and a database layer using Zend_Db/Zend_Db_Table, there is a Zend Framework MVC architecture using models, controllers, views, layouts with Zend_Layout as well as a few view helpers and some HTML, CSS as well as Javascript. All commonly needed. There is more needed to make it a sitethough.

I want as little configuration per site as possible but I naturally still use Zend_Config_Ini for settings. Zend_Registry is needed to keep the global scope clean and is used to store instantiated objects that need to be available throughtout the website logic.

I have been a bit particular on using ZF as often as possible on these sites. With few exceptions. Thus I also use Zend_Form, Zend_Locale, Zend_Translate, Zend_Cache and more. Zend_Cache is really a no brainer and mainly used to speed up translations. This is extremely easy as Zend_Translate and Zend_Locale both are connected to the cache with one simple method call each. It is not complete but how simple this is to setup is illustrated by the below code.

$configuration = new Zend_Config_Ini(
    APPLICATION_PATH .'/config/app.ini',
$frontendOptions = array(
    'lifetime' => $config->cache->lifetime,
    'automatic_serialization' => true
$backendOptions = array('cache_dir' => $config->cache->dir);
$cache = Zend_Cache::factory(

$conf_locale = $configuration->locale;
$locale = new Zend_Locale($conf_locale);

$translate = new Zend_Translate(
    APPLICATION_PATH .'/config/translation-' . $conf_locale . '.php',

Zend_Form have had a few problems in many versions of ZF. In my opinion it is also a bit bloated and limiting to be used all the way. (Even though I like the automatic connection to the translation functionality in Zend_Translate and the validation through Zend_Validate) So I have settled for a simpler way where I use Zend_Form fully for validation (with Zend_Validate) and then give the view access to the form through a Zend_Form subclass to be able to print the fields individually. I think this is easier to handle than all the overloading and coding needed to fully make Zend_Form create forms as I want them. Another good thing with the form classes is that they too are locale aware and are translated automatically by connecting them to Zend_Translate through the simple line Zend_Form::setDefaultTranslator($translate);. The sub classed Form utility class looks like below. The generated elements are translated automatically. Very convenient.

class Custom_Form extends Zend_Form  {
     * Render a field
     * @param string $name The name of the form element
    public function _e($name) {
        $e = $this->getElement($name);
        return ($e) ? $e->render() : "<dt>Error</dt><dd>Missing <$name> field element</dd>";

Another thing needed for these sites are to keep the urls understandable and thus translated into the language used on the site. For this the routes, or paths, are kept in the translation file as well. The translated paths are then registered to the router through the use of Zend_Controller_Router_Route and Zend_Controller_Router_Route_Regex objects.

$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
    new Zend_Controller_Router_Route(
        array('controller' => 'review', 'action' => 'index')

For image manipulation I haven’t looked further than ImageMagick. After a bit of tweaking you get very good quality when producing different image sizes.


Last but not least, on the backend that is, there’s the search engine. ZF have an implementation of Lucene through Zend_Search_Lucene (derived from the Apache Lucene project). This is the one time I haven’t gone with ZF as I very much like the open source Sphinx search engine as it is so easy to integrate with MySQL. So Sphinx get to power the search.

This is convenient for several reasons. MySQL is not a great full text search engine, Sphinx give you better weighted results. The main reason though is the performance. Sphinx is very fast in itself but for a site with heavier traffic it is as simple as moving the search backend to it’s own machine to get a performance increase.


On the frontend there is as clean html as possible to make it easy to change the design with only CSS as well as manipulate the client side with JQuery. If it wouldn’t be for the Google map the site would actually be pretty useful even without no css style at all.

A good practice I learned just recently (remember I’m mostly a backend developer) is to base all javascript functionality on modules that are instantiated depending on element ids present in the html. This makes it a lot simpler to split the javascript functionality into manageble pieces and also makes it a lot easier to maintain.

There are functionality in the client side javascript used to display error messages and information. This makes it necessary to create one javascript file with translation stirngs for each language. The correct javascript translation file is chosen in the layout (template/view file) depending on the current locale.

The map used is (are there any alternatives) Google Maps API. I chose to completely initiate the map by scanning the actual data displayed on the page. This is possible through clean html markup and also means that if I choose to list ten reviews on a page instead of five nothing need to be changed at all in the frontend. Only a loop limit on the backend.


Well. No conclusion. This was just a very basic walkthrough of most of the different pieces needed to create a fairly simple Zend Framework based website. Mostly it was a walkthrough of the bootstrap… I still hope it is useful or at least interesting.

I know I find it interesting to read about other sites and the architecture and design behind them.

Tagged with: , , , , ,
Posted in PHP
2 comments on “Site architecture based on Zend Framework
  1. Your comments about rendering forms are actually addressed in a series of blog posts I wrote. At this time, you can call render{DecoratorName}() on any given element to render just that decorator. This makes it trivial to do as you suggest — grabbing the form and rendering individual elements directly in your view script. I often will make use of renderViewHelper() renderLabel(), and renderErrors() on my elements as these are the parts I don’t want to add custom logic for, but then intersperse these calls with more custom HTML.

    Regarding search, a number of contributors have indicated they’re working on Sphinx adapters, but no public proposals exist yet. I’d love to see proposals for both Sphinx and Solr. If you have time, perhaps you could aid in Sphinx development? :)

    Nice writeup, and I’m glad ZF helped you complete your project!

  2. Danne says:

    Would be interesting for sure. Unfortunately I won’t have the luxury of spending time on unpaid projects until spring…

1 Pings/Trackbacks for "Site architecture based on Zend Framework"
  1. [...] a new post to his blog Danne Lundqvist compares two sites he used the Zend Framework for – a tourism guide for [...]

Leave a Reply

Your email address will not be published. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>