Deprecated Behaviour

The inane, sometimes insane, ramblings from the mind of Brenton Alker.

Building a Modular Application in Zend Framework - Part 2

Welcome to part two of the series exploring the modular application structure in Zend Framework. With the basic application set up in part one, we can get down to actually creating our first module. We’re going to refactor the official quickstarts guestbook. This will let us focus on the modular structure without getting bogged down in business logic.

Note, there are still some bugs in Zend_Tool that prevent this working as it should, I will note the bugs and their fixes as we encounter them.

Create the module

From the base path of our application (/WORKING/PATH/aza from the last article), we can issue the command to the Zend_Tool CLI to create our guestbook module.

zf create module guestbook

Then, create the index controller within the guestbook module.

zf create controller index 1 guestbook

The “1” argument tells Zend_Tool that we want to automatically create an index action within the new controller. We can get a help listing like this:

zf create controller ?

Once the new module and controller is created we need to tell the application that we are using modules. We do this by adding two lines to the configs/application.ini. The first activates the modules resource. The second configures the front controller, telling it where the modules are located. These lines should be added to the end of the production section of the .ini file.

resources.modules = ""
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"

To check our module is working, we can navigate to our guestbook at http://aza/guestbook and we should see the default view for the index action.

Bug: Zend_Tool doesn’t prefix the controller names within the module name. The guestbook index controller class IndexController needs to be changed to Guestbook_IndexController. Bug: The default view for the controller is the same as the main page, it shouldn’t be but we don’t really care, we’re going to replace it anyway.

Create module bootstrap

In the same way that the Bootstrap.php set up the environment for our main application (also known as the default module) each module has its own Bootstrap.php that adds anything additional that each module needs. Zend_Tool doesn’t create this bootstrap by default, so we need to create application/modules/guestbook/Bootstrap.php and it should contain.

1
2
3
4
<?php
class Guestbook_Bootstrap extends Zend_Application_Module_Bootstrap
{
}

By creating this file, the application will automatically perform module bootstrap tasks such as adding autoloaders for the default resources; including models, forms and services. Any other module specific bootstrapping tasks can be added as _init*() functions. In our case, we don’t need any further bootstrapping.

Important note: All bootstrap functions for every module are run for every request.

The bootstrap process occurs before routing and dispatch, so during bootstrap there is no way to know which module/controller/action is being requested. Therefore, any setup that should be done only if a particular module is requested should be done in plugins, not bootstrap.

Getting Quickstart

Now we have the module skeleton in place, lets start porting the guestbook code to our module. This turns out to be fairly easy; the majority of the changes involve prefixing class names with the module name.

To make life easy, start by acquiring a copy of the completed quickstart application (it’s on the right hand side in zip or tar.gz form).

Importing Quickstart

Once you have downloaded and extracted the files into a temporary folder, we can start copying in the files we need.

We need to copy the GuestbookController from the Quickstart (making it the IndexController) and all of the Quickstart models, views and forms to the appropriate places within our module.

From (Quickstart)To (Aza)

application/controllers/GuestbookController.php

application/modules/guestbook/controllers/IndexController.php

application/models/* application/modules/guestbook/models/

application/views/scripts/guestbook/* application/modules/guestbook/views/scripts/index/

application/forms/* application/modules/guestbook/forms/

The controller and the views will require overwriting the existing files.

Porting Quickstart

Now we have the files in the right place, we need to update the files to be modular.

We’ll start with the easiest one, the form. It is simple because it is already prefixed for the Default module, all we need to do it change the prefix to Guestbook_. So the class in application/modules/guestbook/forms/Guestbook.php changes from Default_Form_Guestbook to Guestbook_Form_Guestbook.

Now the models. There are many more changes here but they are just as simple because the models (like the form) are already prefixed with “Default”, but the classes also contain references to each other, so we need to change more than just the class names. A simple search and replace of “Default” with “Guestbook_” in the application/modules/guestbook/models/ directory is all we need.

The controller is a little trickier because it isn’t already prefixed (controllers in the default module aren’t), but it’s still not too hard. The name of the class in application/modules/guestbook/controllers/IndexController.php just needs to be changed from GuestbookController to Guestbook_IndexController, as it has changed from the guestbook controller within default module (no prefix) to the index controller within the guestbook module. We also need to update the references to the models and forms, the same search and replace as we used in the models will suffice.

Finally, we get to the view. In our index view (application/modules/guestbook/views/scripts/index/index.phtml) we need to update the parameters passed to the url helper to reference our controller. Adding the module, and changing the controller leaves the first link looking like this:

1
2
3
4
5
6
7
8
<p><a href="<?php echo $this->url(
    array(
        'module'    => 'guestbook',
        'controller' => 'index',
        'action'     => 'sign'
    ), 
    'default', 
    true) ?>">Sign Our Guestbook</a></p>

Done!

Connect the database

I’ll leave the actual creation of the database to you. It is he same as the Quickstart and this post is already particularly long. You will need to create the database, and add the configuration to the application.ini.

Conclusion

We have just ported the Quickstart guestbook application to a Zend Framework Module. Modularizing applications allows for easier code reuse across applications. Hopefully modules will become standardized to the point that there will be a repository of modules that can be added to your application and providing drop in functionality.

Download

For those who had trouble following along, I’ve made the entire application (including database) available via my github repository.

Building a Modular Application in Zend Framework - Part 1

This is part one of a series exploring modular application development in Zend Framework. In this entry we’ll look at downloading and installing Zend Framework, especially Zend_Tool, on a Linux environment. We’ll start from the beginning so that future posts can build on a known environment. Throughout this post, the code snippets are copy/paste ready, so following along should be easy, just start in a new working directory.

Install Zend Framework

The first step is to actually get ZF, so start by downloading the package (about 40MB in total) into our working directory and extracting it.

wget http://framework.zend.com/releases/ZendFramework-1.8.4/ZendFramework-1.8.4.tar.gz
tar zxf ZendFramework-1.8.4.tar.gz

We’ll then create a symlink to provide an easy upgrade path (extract the new version and move the symlink), and an easier to remember directory name.

ln -s ZendFramework-1.8.4 ZendFramework

Install Zend_Tool

Creating an alias allows command “zf” to always point to the Zend_Tool shell script, so we can use the command line tool from wherever we need it.

alias zf=`pwd`/ZendFramework/bin/zf.sh

Now the installation is complete, we should be able to check what version of the framework we have just installed.

zf show version
# Zend Framework Version: 1.8.4

If this works, we’re ready to start creating our project. The documentation provides some alternate methods of setting up Zend_Tool, including setting it up in a windows environment.

Create the project

Once Zend_Tool is working, we can begin creating our project. For the exercise, we’ll call our project “aza” (A Zend Application). Using Zend_Tool, we create the basic structure for the project.

zf create project aza

This should produce a project structure that looks like this

[caption id=“attachment_131” align=“alignnone” width=“324” caption=“Directory Listing of new project”]Directory Listing of new project[/caption]

Setup the web server

Finally, we can tell the Apache2 web server about our application by adding a VirtualHost to the server configuration. You will need to replace “/WORKING/PATH/” with the absolute path to the directory in which you are working (run pwd if you’re not sure).

<VirtualHost *:80>
    ServerName aza
    DocumentRoot /WORKING/PATH/aza/public
    <Directory /WORKING/PATH/aza/public>
        php_value include_path "/WORKING/PATH/ZendFramework/library"
        php_value magic_quotes_gpc 0
        php_value short_open_tag "on"
        DirectoryIndex index.php
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

Don’t forget to restart the web server to enable the site.

Test our page!

We should now be able to navigate to our site and be warmly welcomed to our new Zend Framework application! We’ll stop here for now. In the next post, we’ll start looking at creating our first module.

Updates

2009-06-26 Updated for ZF Version 1.8.4

Re-sequence a Column in MySQL

When you have an “position” column in a table, to allow the user to select the order of elements in the table or as an optimization for pagination. They always seem to get out of sequence at some point—ending up with gaps in the sequence. This is something I run into not quiet often enough to remember how to do it, yet often enough to to be frustrating. So here is an easy solution to re-sequence the position column in a table, maintaining the current order, just closing any gaps.

SET @pos := 0; UPDATE Example SET position = @pos := @pos + 1 ORDER BY position

It simply initializes a variable (@pos) to 0, then for each row (updates are done in sequence) increments the variable and assigns it to the position column. The ORDER BY clause ensures the current ordering is maintained. WHERE clauses can also be added as required.