Archive for the 'Zend Framework' Category

Rob Allen’s Zend Framework Tutorial

Friday, August 18th, 2006

Anyone looking for a good comprehensive run through of a Zend Framework application should read Rob Allen’s My Take on a Zend Framework Tutorial.

As it’s a PDF, you might like to read it using this trick from Jon Udell: Vertical PowerBook as ebook reader. He uses a Mac but I’m sure you can achieve much the same on other OS’s.

RewriteRouter and Zend_Config play together

Tuesday, July 18th, 2006

While getting the hang of the Zend_Controller_RewriteRouter, which is now included in Zend Framework 0.1.5, I was adding the routes in my index.php (bootstrap) file and wondered if there was any way of storing them elsewhere. It is possible to loop over Zend_Controller_RewriteRouter::addRoutes() but the method I will describe here is based on some recent updates to Zend_Controller_RewriteRouter by its author Michael Minicki.

The point of RewriteRouter is to map urls, like ingredients.com.au/recipe/tomato_sambal, to whatever controller, action and parameters needed without having to use external (and often painful!) methods like mod_rewrite.

For the sake of this article I’ll use a relatively simple URL…

ingredients.com.au/articles/cooking/

First setup some routes in a config file “routes.php”. Note that this does require the latest version of the RewriteRouter which needs to be checked out from the subversion repository

$config['routes']['articles'] = 
new Zend_Controller_Router_Route('articles/:category', 
array('category' => 'all', 
       'controller' => 'articles', 
       'action'      => 'index' ), 
       array('category' => '[a-z_]+') );

This establishes a route called “articles” that will respond to any url of the form “/articles/whatever” with the colon in :category indicating that it is an url variable that can be recovered through Zend_Controller_Action::_getParam( ‘category’ ). The controller and action indexes make the action “indexAction” in the controller file “ArticlesController.php” the final target. To cover cases where there is no category specified the default setting “all” is given. For extra assurance :category has to be a string containing only lower case letters and underscores as indicated by the final requirements array.

Next load them into the bootstrap file using Zend_Config_Array:

$routes = new Zend_Config( 
        Zend_Config_Array::load( 
       '../application/configuration/routes.php', 'routes' ) );

Then create the RewriteRouter object and pass it the $routes…

$router = new Zend_Controller_RewriteRouter;
$router->addRoutes( $routes );

All that is needed now is to pass the $router to the front controller…

$controller = Zend_Controller_Front::getInstance();
$controller->setRouter( $router );

That’s it, now the routes are nicely stored outside of the bootstrap file and with the rest of the domain files.

Further Reading

Aside from the manual pages mentioned I can’t close without pointing to an actual recipe for tomato sambal !!

Endnote

I should also mention that it’s well worth getting involved with the development of the framework even if you can only do so in a small way. After a relatively short discussion via the issue tracker about having some means to load routes in one hit, Michael Minicki had implemented one (thanks Michael).

Zend Frameworking underwater.com.au

Tuesday, July 4th, 2006

Now that the host for underwater.com.au has upgraded to PHP5 I’m working on migrating it to use the Zend Framework. I thought it may be interesting to run through a few of the reasons I’ve chosen to do so especially while the framework is in such an early stage of development.

“Underware”

The engine, code-named “Underware”, that underwater.com.au currently runs on is built almost entirely (excluding a few additional class files) from my own code. Developed, via several projects, over the course of about five years from a modified version of the PHP e-Commerce application Freetrade and the FreeEnergy structure (Actually, it’s interesting to look back over that FreeEnergy article to see how it’s almost a Model-View-Controller structure), Underware is now more object-oriented, more MVC’ed and more woven with design patterns than its early incarnations, however it still has loose threads.

Why grow your own?

Considering the amount of freely-available, open-source, PHP code it seems idiotic to be doing it all yourself. Sadly, the number of applications available is no indication of their quality, nor whether they will play nicely together, a point taken up by Clay Loveless in his Stop Writing Loner Applications post.

At every stage of Underware’s development I looked at pre-existing solutions, hoping to find one that wouldn’t force me to duplicate components I already had, such as user management. It wasn’t necessarily that I had better code, more that what I did have was only what I needed. Besides, I knew as I worked on it the code quality would also improve. Inevitably, after spending many unbillable hours pouring through different solutions I’d look at the clock and think “I could have spent those hours moving forward and coding a solution”!

Pros of doing it all yourself

  • You only build, debug and support what you need.
  • You know all the code.
  • You learn a lot.

Cons of doing it all yourself

  • You have to build and support every bit of code and unless you build it it’s not just going to appear from somewhere.
  • You have to document it all.
  • You have to spend time researching solutions to every issue, including system level ones that are not directly providing solutions for your clients.

Thankfully the increasing amount of frameworks available (i.e. rather than finished applications) combined with the growing object-oriented’ness of PHP mean it’s less of an either or situation.

So why Zend Framework?

Honestly, I think because it feels right and I say that not to be facetious, but partly because I see so many lengthy arguments for and against such and such framework as if one or the other holds the golden key. Part of the reason I went back to my roots was to show the influences on my way of structuring web applications and if you’re interested enough to look into them you may see some similarities. For me the Zend Framework not only fits the way I’m currently working but moves it forward, tying up some of the aforementioned loose threads for example.

More pragmatically there are factors like the fact that my clients can worry less about being so totally dependant on me for every facet of their applications; I can benefit from all the external input to the framework itself; I can focus on solving client needs more and system level needs less and not to be ignored is the Zend part of the framework which for me puts at least some stamp of longevity and consistency on the code base.

Some further Underware influences

Some current Zend Framework reading

Custom View Helpers in Zend Framework

Monday, June 26th, 2006

The Zend Framework Manual describes View Helpers like so:

“In your view scripts, often it is necessary to perform certain complex functions over and over; e.g., formatting a date, generating form elements, or displaying action links. You can use helper classes to perform these behaviors for you.”

Currently the framework (version 0.1.3) includes a small selection of form helpers which will no doubt expand as it matures. For now I’m more interested in the ability to add custom helpers for specific project use. The first thing I did was to set up the same directory structure as Zend_View_Helper as is suggested when subclassing controllers:

library/
    Zend/
        View/
            Helper/
    MyProject/
        View/
            Helper/

Having my project specific helper files in library/MyProject/View/Helper/ will make it easy to keep them separate from Zend core updates.

The next step is to tell Zend_View to look in the custom helper directory as well as the default Zend helper directory. This just requires adding the new helper path to the Zend_View object I created in the public_html/index.php file:

$view = new Zend_View;
$view->addHelperPath('MyProject/View/Helper');

Cautionary Note (* see update below)

The above is actually a bit of a fiddle to get working if you decide like I did to use a relative path to your helper files. I had set…

set_include_path( /home/exciting_zfw_site/library/ );

…pointing to the main Zend library directory, however, Zend_View_Abstract:: _loadClass() uses is_readable() as a check before loading any helper or filter files like so…

if (is_readable($dir . $file)) {
    include $dir . $file;

    if (! class_exists($class, false)) {
        $msg = "$type '$name' loaded 
                        but class '$class' not found within";
        throw new Zend_View_Exception($msg);
    }

    return $class;
}

…and since is_readable just ignores include paths, your new helper files won’t be found. This is currently listed as a bug but for the moment I simply changed…

if (is_readable($dir . $file)) {
    include $dir . $file;

…to…

if (include $dir . $file) {

…and it worked fine. Portability was the reason I wanted to keep the paths relative as I move files from a development server to the live server. It’s much easier to keep as few path configuration settings as possible.

The next step is pretty well documented in the manual but for the sake of completeness I’ll keep going. Create a new helper file:

class Zend_View_Helper_DoStuff {

    public function doStuff()
    {
        return 'Hello to you all';
    }
}

Another Cautionary Note

Something that caught me out was that the new helper class must be called Zend_View_Helper_YourNameHere rather than MyProject_View_Helper_YourNameHere which seems a little odd considering it’s position in the directory structure I mentioned before. While logically it is a Zend_View helper class, it will be kept with other subclassed files with your own “namespaced” class names under the MyProject directory so it seems to break a convention.

Ready to use

After saving the new helper file in MyProject/View/Helper/DoStuff.php it should be available to use in your view scripts like so:

<?php echo $this->doStuff(); ?>

When writing helper classes the key points to initially getting them to work are the naming conventions as illustrated by my doStuff example:

  1. Class name must be Zend_View_Helper_DoStuff
  2. The class must contain a public function doStuff()
  3. The file must be save as DoStuff.php

As mentioned in my post on getting to know Zend_View elements of the above may well change as development continues.

Further Reading

View Helpers in the Zend Framework Manual

* Update

Forget the above hack…

if (include $dir . $file) {

…as it will produce warnings as Zend_View_Abstract::_LoadClass() attempts to include the doStuff file from any other path in the _path stack. Instead the only solution I’ve found to currently work is to specify a relative path like so:

$view->addHelperPath('../MyProject/UW/View/Helper');

Getting to know Zend_View

Saturday, June 10th, 2006

Like many other PHP developers I’m keeping an eye on the progress of the Zend Framework. It’s currently still in the very early stages of development but is nonetheless worth “getting to know”. These are some notes from a play around with the current View functionality.

I generally use a nested layout template file with PHP embedded in HTML. Variables are assigned by a controller file so a layout template may look like this “main_layout.php” file:

<body>
    <?php include 'modules/header.php'; ?>
    <?php include $page; ?>
    <?php include 'modules/footer.php'; ?>
</body>

After some much appreciated help from Paul M Jones and Simon Mundy on the Zend Framework General List, I now have the following three methods of doing the same in the Zend Framework.

Use Zend_View::_script()

Include the additional views directly in the layout using the Zend_View::_script() method:

<body>
    <?php include $this->_script('/modules/header.php') ?>
    <?php include $this->_script( $this->content ); ?>
    <?php include $this->_script('/modules/footer.php') ?>
</body>

Use assigned variables

Assign the additional views in the controller file and then use the variables in the layout:

In the view controller:

$view->header = $view->render('modules/header.php')
$view->content = $view->render('page.php')
$view->footer = $view->render('modules/footer.php')

In the view script:

<body>
    <?php echo $this->header; ?>
    <?php echo $this->content; ?>
    <?php echo $this->footer; ?>
</body>

Use Zend_View::render()

This seems to be the “proper” solution as it makes full use of the _file stack in render().

Call Zend_View::render() from within the view script:

<body>
    <?php $this->render('modules/header.php') ?>
    <?php $this->render( $this->content ) ?>
    <?php $this->render('modules/footer.php') ?>
</body>

The above three solutions all require a final call to render the whole layout in the view controller file, e.g.:

echo $view->render( 'layouts/main_layout.php' );

Cautionary Note

Since the framework is currently in preview release stage it’s possible that the above may change soon after posting this (though I suspect probably not much if at all).

Update (8th November)

As of the latest SVN checkouts Zend_View::render() does not echo the output so you will need to use…

<?php echo $this->render( $this->content ) ?>