Tag Archives: Front Controller pattern

Setting Up Zend Framework with Modules

Typical Zend App

Typically you’ve one module in your Zend App – the default one. In the basic installation of the framework, you put all the controllers, models and views directly in the application folder, as described below.

/application
	- /controllers
		- /IndexController.php
	- /models
		- /MyModel.php
	- /views
		- /scripts
			- /index/index.phtml
/library
	- /Zend
/public_html
	- /images
	- /scripts

Bigger Apps – More Code

When the application becomes bigger and bigger the controller, models and views/scripts directories contain more and more files. That’s a bit odd, because it becomes difficult to maintain, and than the modules come in hand.

Modules in a Zend App

When it comes to setting up modular Zend App there are tons of articles in the web, but let me show you a simple directory layout and … sample code that sets up the framework.

/application
	- /modules
		+ /admin
			- /controllers
				- /IndexController.php
			- /views
				- /scripts
					- /index/index.phtml
		+ /default
			- /controllers
				- /IndexController.php
			- /views
				- /scripts
					- /index/index.phtml
	- /models
/library
	- /Zend
/public_html
	- /images
	- /scripts

Source

Simply add this into the bootstrap:

$frontController->addModuleDirectory(APPLICATION_PATH . '/modules');

Setting Up Global Cache in Zend Framework

In a large scale web application, especially based on Zend Framework, there are lot’s of components that support built in cache support. Such are Zend_Db, Zend_Translate, Zend_Date, etc. Also you may need cache support wherever in the app, so my advice is to setup a cache instance in the “beginning”, into the bootstrap.php or even better – into a front controller plugin, and to store it into the Zend_Registry. Thus you’ve to change only the lifetime for specific needs:

<?php
 
class CacheInit extends Zend_Controller_Plugin_Abstract
{
    public function __construct()
    {
        $frontendOptions = array(
            'automatic_serialization' => true,
            'lifetime' => 60
        );
 
        $backendOptions  = array(
            'cache_dir' => realpath(APPLICATION_PATH . '/../cache')
        );
 
        $cache = Zend_Cache::factory('Core',
                                     'File',
                                     $frontendOptions,
                                     $backendOptions);
 
        Zend_Registry::set('cache', $cache);
    }
}

Than add it as a front controller plugin:

// cache plugin
$frontController->registerPlugin(new CacheInit());

Zend Framework: Simple Acl Front Controller Plugin

access with Zend_Acl

Almost every web site need some abstraction over the access control list (ACL) to grant access of its users. As usual Zend Framework has quite good mechanism to deal with this – Zend_Acl.

Out in the web there are a lot of resources about Zend_Acl’s usage, so I ain’t going to cover it one more time, but simply copy/paste a very small front controller plugin implementing the basic usage of Zend_Acl.

Note that instead of defining the __construct() here is called preDispatch where the request is passed as a parameter. However only by copy pasting not every answer will be given. That’s why I’m going to write more about Zend_Acl in my future posts, for now only the source code:

<?php
 
class AclInit extends Zend_Controller_Plugin_Abstract
{
    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        // create new acl object
        $acl = new Zend_Acl();
 
        // define resources. typically there are
        // only four resources from the CRUD functionality
        // but there can be added more resources
        $acl->add(new Zend_Acl_Resource('index'))
            ->add(new Zend_Acl_Resource('create'))
            ->add(new Zend_Acl_Resource('read'))
            ->add(new Zend_Acl_Resource('update'))
            ->add(new Zend_Acl_Resource('delete'));
 
        // define roles
        $acl->addRole(new Zend_Acl_Role('guest'))
            ->addRole(new Zend_Acl_Role('admin'));
 
        // define privileges
        $acl->allow('guest', array('index', 'read'))
            ->allow('admin');
 
        // setup acl in the registry for more
        Zend_Registry::set('acl', $acl);
 
        // check permissions
        if (!$acl->isAllowed('guest', $request->getActionName())) {
            $request->setControllerName('error');
            $request->setActionName('error');
        }
    }
}

Custom Routes with Zend_Controller_Router_Route

Rewrite The Url?

Actually this is really a common task to do. You’ve to rewrite the url to be more “user friendly”. To be more clear I’ll give you an example. Let’s imagine you have a index controller and an index action. Thus if you have to load an Id from the database at least with the build in Zend Framework capabilities, you’ve to use this link:

www.example.com/index/index/id/33949

This is not good. It’s really bad. It will be great if you can use something like this:

www.example.com/33949

The solution in Zend Framework is called Zend_Controller_Router_Route. In a short snippet this will look like so:

$frontController->addRoute("my-route", new Zend_Controller_Router_Route("/:id",
    array("controller" => "index", "action" => "index", 'id' => 1),
    array('id' => '\d+')));

Here as you can see id is set to be 1. But don’t worry that’s not a hard code. The real work is done by the last parameter where the id is matched against a number value. Thus www.example.com/3 will be OK, but www.example.com/3a won’t.

Important Note

Don’t forget to add this rewrite rule in the .htaccess file.

Zend_Date – make it work and benefit with locales

Although the documentation of Zend Framework is one of the most well structured documentation I’ve ever read it happened to me to stuck into it. And that happened exactly when I tried to use the date component of ZF – Zend_Date.

Why I’d prefer Zend_Date?

We all know what the date function of PHP is, and what it does. It has reach set of formating string that help you do the job but as I’m working mostly on multilingual projects almost every project needs multilingual dates, and more or less nobody wants only numbers into the dates. And all this is pretty natural, instead of using the simple

01.01.2010

format, which beside it’s natural ugliness is not clear. Because as you may know in the US this can be understood as month.date.year, while in Europe this is date.month.year. And when it comes to dates like 02.01.2010 this can be really frustrating.

Beside this ugly format, you can choose to format your dates either with:

1 January 2010 or 1 Jan 2010

which is clear enough, but it’s only for english speakers. You know that in a spanish speaking country you should format the same date as:

1 Ene 2010

where “ene” means enero – january in spanish. How should you overcome this natural PHP problem?

Well the answer is by using Zend_Date

The problem I found in Zend_Date usage is that the native copy/paste technique from the doc page doesn’t seem to work. What the doc page says you is:

// setup the default timezone
date_default_timezone_set('Europe/London');

and than you can simply request a date with:

$date = new Zend_Date(‘2010-01-02’);
echo $date->get('d MMM yyyy');

where this should print 1 Jan 2010.

It’s a shame that this doesn’t work. The good part is that this problem can be overcome very simply. You just need to setup some more things just before calling the get method.

First setup a cache mechanism where you can cache the date locales. This is really good practice because it speeds up the framework when dealing with dates. Just add those lines after the default timezone is set:

// setup the default timezone
date_default_timezone_set('Europe/London');

$locale = new Zend_Locale(‘es_ES’);
Zend_Registry::set('Zend_Locale', $locale);

$frontendOptions = array(
		'lifetime' => 600, // 10 minutes
		'automatic_serialization' => true
);

$backendOptions = array(
                'cache_dir' => '../cache/'
		);

// getting a Zend_Cache_Core object
$cache = Zend_Cache::factory('Core',
		             'File',
		              $frontendOptions,
		              $backendOptions);

First you setup the Zend_Locale – a locale for the entire application and set it up in this example for spanish, than setup the cache mechanism.

This is a typical cache setup for Zend Framework. If you’d like to dive more into cacheing you can checkout the doc pages for Zend_Cache.

After these lines just setup Zend_Date options with:

Zend_Date::setOptions(array('format_type' => 'php',
                   'cache' => $cache));

This is really what you need to do to start. All these lines of code you may place into the bootstrap.php or into some front controller plugin.

Then you can call Zend_Date’s get method wherever you’d like in every controller you need it!