Using Zend_Db With Silex

I’ve been messing around with Silex (and of course Symfony2) a lot lately, and I was excited to see a Doctrine extension. However, it was only for the DBAL and not the ORM. In my symfony2 apps, I’ve finally adjusted to using Doctrine’s ORM, but for some reason, I’ve really grown to like the DBAL that Zend_Db offers over the pseudo SQL (DQL) that Doctrine has. Here is a quick Extension to get you started with Zend_Db.

<?php
 
namespace SyndExtension;
 
use SilexApplication;
use SilexExtensionInterface;
 
class ZendDb implements ExtensionInterface
{
    public function register(Application $app)
    {
        $app['autoloader']->registerPrefix('Zend_', $app['zend.class_path']);
 
        $app['db'] = $app->share(function() use ($app) {
            return Zend_Db::factory($app['db.adapter'], array(
                'host'     => $app['db.host'],
                'dbname'   => $app['db.dbname'],
                'username' => $app['db.username'],
                'password' => $app['db.password']
            ));
        });
    }
}

Create that under ./src/Synd/Extension/ZendDb.php. To use it, you’ll need to add Synd to your autoloader, and then register the extension in your application:

$app['autoloader']->registerNamespace('Synd', 'src');
 
$app->register(new SyndExtensionZendDb(), array(
    'db.adapter'      => 'mysqli',    
    'db.dbname'       => 'your_db',
    'db.host'         => 'localhost',
    'db.username'     => 'root',
    'db.password'     => '',
    'zend.class_path' => '/path/to/zf/library'
));

Please note that this is a quick and dirty bridge, and is for ZF1 not ZF2. If I’m breaking any best practices with naming and combining libraries, be sure to let me know. I’m hoping to explore the Zend_Db and Zend_Form combination since I use them heavily in my apps. This provides a very lightweight infrastructure in order to throw up quick proof of concept applications.

Hopefully this helps someone… or at least gives enough familiarity for my ZF buddies to start looking at Silex / Symfony2.

Zend Framework Models – Part 1: Concepts

The power in Zend Framework lies in its uncompromising flexibility. However, evidently, this also means its very difficult for new ZF users to pick up the framework and hit the ground running. The most common question I see is usually “where is the model?”. The goal of this post is to show some examples and hopefully some new ideas on how to tackle models. There is no one-size-fits-all solution folks. Let’s look at some options and some background…

The concept of a model

Before we can go any further, we must first figure out what a model is. This stuff isn’t an exact science, so there will be some gray areas. Much of this post is my opinion (read: not fact). This doesn’t necessarily make them right or wrong. I like to think I’m right, so feel free to argue with me in the comments below.

In an MVC application, the model is responsible for all the business logic. The controller should handle flow control (taking input, calling models, redirection, etc.), and the view is responsible for representing your application, usually with some sort of data language (XML, HTML, JSON, etc.)

Implementation and and interpretation of the pattern is up to the developer… there are some gray areas so don’t worry if it doesn’t meet the exact specification. However, one thing I like to practice is skinny controllers, fat models. By shifting a lot of the work to the models (and their underlying libraries) you can usually organize your application much better. The result is simpler and more organized (primarily better encapsulated) code.

Simply said, a model should contain your business logic. Any processing that revolves around your application data should probably be put into models. I consider a model to be anything that does something in the big picture of your application… things like reading/writing data, sending/receiving data, processing data. They do the “work”.

One mistake I see is people simply setting up ORM (ex: Doctrine) models for each of their tables and leaving it at that. Your models’ public interfaces should be very simple. I prefer to have their interface represent their actual domain logic. For example, if you are making a post, then your controller (or calling code) should simply call something very self explanatory like post->create( info ). One personal guideline I follow is not to have more than 4 or 5 parameters to a method, and ideally, only 1 to 3.

One common implementation of this annoyance of mine is putting in chained query calls in your controller. Yes, the actual database code is encapsulated, but you are still revealing way too much information in your controller. The whole point of them is to encapsulate not only the code, but also the underlying logic. This way, when your business logic changes, your controllers can usually continue to function properly.

Working with databases

Most web applications revolve around storing information in the database. Whether it’s posts, comments or pictures, it all boils down to the same few operations. You can call this CRUD: create, read, update and destroy. In practice, it’s often much more complicated… but they remain to be the underlying concepts for most database interaction.

Most other frameworks come with a default model class/component which is a huge push in the right direction. Zend keeps an open mind about it, providing a few tools to use if you want to work with the database. Zend comes with a huge Zend_Db component to handle your database operations. It also contains Zend_Db_Table which is an implementation of the Table Data Gateway and Row Data Gateway patterns.

Personally, I’m not a big fan of Zend_Db_Table. I still think Doctrine is much more powerful, though I do really like Zend_Db. It operates under some of the same principles as PDO (database abstraction layer), so if you have used that before, you will be at home. I also really like Zend_Db_Select, which is what the table classes use quite a bit.

Using a base model

Because there are so many different types of models, I don’t think there is much point in having a do-it-all base class. However, for the group of models that will need database access, I use something like this:

class Site_Model {
    protected $_db;
 
    public function __construct(Zend_Db_Adapter_Abstract $db) {
        $this->_db = $db;
    }
}

You can probably tell that the default model is not even needed… and that’s the point. However, depending on your needs, this is a good place to start adding some common functionality that your db models will need. You may want to also make them all loader or dependency injector friendly if your application requires that.

Zend_Db

Zend’s database abstraction layer is really nice to work with. If you use it in combination with Zend_Db_Select you can make the database end of your application very portable. Here are some common methods I use from Zend_Db:

query(string)

fetchOne(query)
fetchRow(query)
fetchAll(query)

insert(table, data)
update(table, data, where)
delete(table, where)

quote(value)
quoteInto(string, value)

Abstracting your queries

If I’m working on an application that I plan to release to the public, then I always use Zend_Db_Select. It works on the same concept as the above insert/update/delete methods, meaning that you never have to write any of the SQL. If you let the Db libraries do it, then you are able to get much more portable code. Zend_Db supports IBM’s DB2, MySQL, MSSQL, Oracle, PostgreSQL and SQLite, so Db_Select is targetted at the same databases.

The concept of Zend_Db_Select is that the query is an object, and you can add/modify different parts of it. This gives you a lot more flexibility over dynamic query creation, as well as the added bonus of portability.

Summary

For your basic database-oriented models, all you your class will need is access to the Zend_Db_Adapter_Abstract interface. Keep your public methods very domain-oriented and your controllers will thank you for it. Break out of the mindset that models = database tables, or even model = database. Usually only around half my models deal with database operations. ZF also has a ton of service libraries available to help with all the common social sites APIs out there.

The next installment of this post will go into some concrete examples and also some ideas on how to implement your models. Comments and criticism welcomed and appreciated as always.

Testing Zend_Mail

Since I work on a local development machine/server, I’ve never taken the time to set up mail yet, nor do I want to. I think a staging environment is more appropriate to actually have email being sent out. Nevertheless, it has made testing any email functionality a little cumbersome. I’ve done a little research, and have found two ways to tackle the problem. I’ve also included code samples and other resources to get you started.

Create a new mail transport class

Zend has the ability to set a default mail transport class to be used when none is specified, which I’d imagine to be 99% of the time. To set it, all you need to do is put this somewhere early in your application before any mail code is executed.

Zend_Mail::setDefaultTransport(new Site_Mail_Transport_Debug());

The alternative (for the 1% who want to manually specify), you’d simply pass an instance of your mail transport object to Zend_Mail::send() when you call it. What should your class contain? It has to extend Zend_Mail_Transport_Abstract, which at this time of writing this, will specifically need to override the abstract _sendMail() method.

You can use it to create a new record in your database, create a file, or do whatever you need it to. I quickly hacked together one to log it to the database, and based it off of the Sendmail transporter, which is pretty much a wrapper for PHP’s mail function. Here is the code I came up with for those who want some direction. It’s very basic, but should be enough to get you started.

<?php
 
class Site_Mail_Transport_Debug extends Zend_Mail_Transport_Abstract {
 
    public function __construct(Zend_Db_Adapter_Abstract $db) {
        $this->_db = $db;
    }
 
    public function _sendMail() {
        $this->_db->insert(
            'mailtest',
            array(
                'recipients' => $this->recipients,
                'subject'    => $this->_mail->getSubject(),
                'body'       => $this->body,
                'header'     => $this->header
            )
        );
    }
}

Override it at the server level

This is a good idea if you don’t use Zend Framework, or don’t use it for all of your applications. There are two great techniques described on akrabat’s blog. Here they are.

The first, is to override php.ini’s ‘sendmail_path’ and create your own script to handle it. If you were to set it to

sendmail_path = /usr/local/bin/trapmail

then you’d use the following code

formail -R cc X-original-cc 
  -R to X-original-to 
  -R bcc X-original-bcc 
  -f -A"To: [email protected]" 
| /usr/sbin/sendmail -t -i

This requires you to have mail configured on your server, but it still solves the underlying problem of wanting to debug the emails, and also not send out test emails to real users in your application.

The second solution provided is platform independent is for Windows users, and it’s to install fakemail. This program acts as an outgoing mail server, but instead creates files containing any mail passed to it.

Hopefully this helps others out who are also frustrated with dealing with pesky email debugging.

Caching Zend Framework Forms

Generating a form is an expensive process in ZF. It’s always bugged me that I can’t find any resources on trying to cache the initial HTML anywhere, so I took a stab at it myself. I use a loader from inside my controller action to load forms and models, so I found that was a good place to start.

Here is my initial loader class, which I have stripped down and simplified for the sake of this example. Ideally, you’d want this in something like an action helper.

<?php
 
class Site_Loader {
    /**
     * Site's controller action
     * @var        Site_Controller_Action
     */
    protected $_controllerAction;
 
    /**
     * Sets the current controller action we're being called from
     * @param       Site_Controller_Action
     */
    public function setControllerAction(Site_Controller_Action $action) {
        $this->_controllerAction = $action;
    }
 
    /**
     * Loads the requested form class
     * Same conventions as Zend (Form_Name = Form/Name.php) class "Form_" . $Form_Name
     *
     * @param    string        The name of the form class
     * @param    string        Any options for the form class constructor
     * @return   object        Form class object - forms_$formName
     */
    public function form($formName, $options = null) {
        $path = APP_DIR . "/application/forms/" . str_replace('_', '/', $formName) . '.php';
        require_once $path;
 
        $class = "Form_" . $formName;
        return new $class($this->_controllerAction, $options);
    }
}

I always find it useful to have access to the controller in forms – especially to access the request information. Another reason is we can use it to determine the request method – more importantly, see if it’s POST. When it’s not, then we can enable caching, because the form output should not change. Only when they actually post something should we need to show anything different. I set a high cache TTL simply because I’d want it to be there forever, until I actually modify the form code, at which point I’d clear its cache. With that in mind, here is the updated (and relevant parts of) the loader.

<?php
 
class Site_Loader {
    /**
     * Site's controller action
     * @var        Site_Controller_Action
     */
    protected $_controllerAction;
 
    /**
     * Caching object used
     * @var         Zend_Cache_Core
     */
    protected $_cache;
 
    /**
     * Sets the current controller action we're being called from
     * @param       Site_Controller_Action
     */
    public function setControllerAction(Site_Controller_Action $action) {
        $this->_controllerAction = $action;
    }
 
    /**
     * Sets the cache object to be used
     * @param       Zend_Cache_Core
     */
    public function setCache(Zend_Cache_Core $cache) {
        $this->_cache = $cache;
    }
 
    /**
     * Loads the requested form class
     * Same conventions as Zend (Form_Name = Form/Name.php) class "Form_" . $Form_Name
     *
     * @param    string        The name of the form class
     * @param    string        Any options for the form class constructor
     * @return   object        Form class object - forms_$formName
     */
    public function form($formName, $options = null) {
        $path = APP_DIR . "/application/forms/" . str_replace('_', '/', $formName) . '.php';
        require_once $path;
 
        $class = "Form_" . $formName;
        return new $class($this->_controllerAction, $options);
    }
 
    /**
     * Loads the requested form class.
     * When request method is post, form is loaded normally.
     * When it's not, cache is used to reduce CPU load.
     *
     * @param   string      The name of the form class
     * @param   string      Any options for the form class constructor
     *
     * @return  mixed       Form class object, or rendered form HTML when caching is active
     */
    public function formCached($formName, $options = null) {
       if ($this->_controllerAction->getRequest()->isPost()) {
           return $this->form($formName, $options);
       }
 
       if ($out = $this->_cache->load($id = $this->_getFormCacheId($formName, $options))) {
           return $out;
       }
 
       $form = $this->form($formName, $options);
       $this->_cache->save($out = $form->__toString(), $id, array(), 31536000);
 
       return $out;
    }
 
    /**
     * Generates the id used for the cache.  It must be unique for the name of the
     * form, and the options passed to it.
     *
     * @param   string      Form name used
     * @param   mixed       Array of options passed to form, or null
     *
     * @return  string      Unique ID for this form cache
     */
    protected function _getFormCacheId($formName, $options = null) {
       if ($options === null) {
           return "Form_$formName";
       }
 
       return 'Form_' . $formName . md5(serialize($options));
    }
}

Enabling Caching

This is generally how a basic form action looks like in my controllers.

public function postAction() {
    $form = $this->loader->form('Post_Create', $options = array());
 
    if ($this->_request->isPost()) {
        if ($form->isValid($this->_request->getPost())) {
            $post = $this->model->create($form->getValues());
            $this->redirector->goToUrl($post->getUrl());
        }
    }
 
 
    $this->view->form = $form;
}

With it enabled, we’d simply change

$this->loader->form()

to

$this->loader->formCached()

Since the only interaction with my form and view script is

<?= $this->form ?>

we don’t even have to change it. The form’s __toString method will work normally when the caching isn’t active, and the form variable is just a string when it is. Simple.

Recap

This will allow for the caching of your rendered ZF forms. It is disabled automatically when the request method is POST, so it can properly re-populate your data and/or show your errors. If you use the simple form renderings in your view scripts, then they will work as-is. This is all just a proof of concept that I am testing on a few sites at the moment. If you have any feedback or questions, don’t hesitate to let me know.

Forms in Zend Framework

I’m often asked what my favorite component of Zend Framework is, and I invariably answer: “Forms”. Forms have always played an awkward role in the model-view-controller paradigm. Sure, the form is just HTML, but to me, it represents something more abstract than that. It represents the HTML form itself, taking user input, normalizing and validating it, and also being able to show the form again when errors occur. This can take quite a large amount of code.

If you’re able to automate all of that stuff, then all you are really left with is configuration. Each form consists of elements, and each element has several attributes which modify the overall functionality of the form. Let’s look at some of these aspects.

Defining a Form

A form itself is an instance of Zend_Form. There are many ways to define one. I prefer to extend Zend_Form for each of my forms, and define them inside the class itself. Each form contains a few important fields (action, method) and also it contains at least one element. Let’s look at how we define an element. Each element probably has a few common attributes: a field type, a label, an element name, and a description. Let’s represent this element in ZF. Note, there are several different ways to represent forms. They can literally be done via configuration, or by a few different PHP methods. This is my favorite.

$username = new Zend_Form_Element_Text('username', array(
    'label'         => 'Username',
    'description'   => 'This is a description'
));

In the above code, you can see we define these three things. There are also some other important attributes for elements. Let’s add a few more, and show a few fields at once.

$this->addElements(array(
    new Zend_Form_Element_Text('username', array(
        'label' => 'Username',
        'required' => true
    )),
));

Filters and Validators

One very helpful feature with the forms component is the ability to chain filters and validators. A filter is something that automatically manipulates incoming data to your desired format, and a validator is something that is checked when processing the form. This greatly simplifies your controller code, and your model code, because you are shifting all of this logic into a much more organized structure.

For example, if you are working with a username element on a registration form, then you may want check that the user does not already exist, the username does not contain any illegal characters, and the username is within a desired length.

If you had an element where the user can enter a few paragraphs about himself, then you would want to apply some filters to make sure the data is clean. You may want to add things like StripTags to remove any HTML, StringTrim to remove any extra whitespace, etc. You could also apply some custom BBCode parsing filters if you wanted. You could create your own filter for this, or use the Callback filter which you can use for everything else.

The idea is to do as much validation as possible so you know that your data is 100% ready for your application. If you have a VARCHAR(255) field, then limit your string to 255 characters so nothing gets truncated. Be very strict.

Filters are more of a time saver to me… but they are nice because they help keep all the data very consistent or can also be part of your cleaning process. If you are allowing user input, then remove any HTML is necessary. You get the idea.

Here is a more complete example of a registration form definition:

$this->addElements(array(
    new Zend_Form_Element_Text('username', array(
        'label'        => 'Username',
        'required'     => true,
        'validators'   => array(
            array('StringLength',      false, array(4, 16)),
            array('Alnum'),
            array('Db_NoRecordExists', false, array('users', 'username'))
        )
    )),
    new Zend_Form_Element_Text('email', array(
        'label'        => 'Email Address',
        'required'     => true,
        'validators'   => array(
            array('EmailAddress'),
            array('Db_NoRecordExists', false, array('users', 'email'))
        )
    )),
    new Zend_Form_Element_Password('password', array(
        'label'        => 'Password',
        'required'     => true
    ))
));

Skinny Controller, Fat Model

With a form containing the fields above, we can really simplify our controller code. To me, controller’s should contain the flow of an application, without really performing any of the work. Here is an example of a registration action.

if ($this->_request->isPost()) {
    if ($form->isValid($this->_request->getPost())) {
        $user->register($form->getValues());
        $this->redirector->goToUrl('/welcome');
    }
}
 
$this->view->form = $form;

If the user has submitted (posted) any information, then the form validates that posted information. If it’s valid, it will proceed to pass the data array to our model. At this point, all of our filters and validators have been executed, so we know exactly how the data is formatted, and that it’s safe to use. We can proceed to redirect the user away, or perform any other flow logic we need to at this point.

We also pass the form to the view, which is crucial. On a regular page view, the form will be loaded normally. On a failed submission, then it will show the form with all of the error messages, and the posted data populated back into the form elements.

View Scripts & Decorators

Here is all the code we need in our view to show a form. The rest can be done via CSS, or custom decorators if we need it.

<?= $this->form ?>

By default, Zend_Form outputs a pretty usable chunk of HTML. I have no problems styling it via CSS which is really great for our separation of concerns. However, there will be times when you need markup in certain format, and Zend can handle this with decorators. They are a little tricky to learn, so I will save that for another blog post. There should be sufficient documentation on their website.

Dealing with Models

As per our controller code, the model would receive $form->getValues(), which would be a pre-validated and pre-filtered array of our data. Here is an example:

// ...
public function register(array $user) {
 
}
// ...

To me, this is beautiful. We are working with a very basic interface, and do not have to manually specify every value that we pass or expect. While this is personal taste, I cringe whenever I see people pass 5-10 values to a model. Their controllers all end up being huge. The code is also not dependent on our form, because it’s just dealing with an array of data. It makes calling our models very simple, too. The model is where the code should start to get complicated. From this point, we can use our database adapter object, or deal with several other libraries.

Summary

The form component is one of the larger (largest?) components in Zend. Don’t be afraid to ask for help on the different forums, or ask below and I can point you to a good resource. Like I said above, this is the most useful component in Zend to me, so if you are considering taking the time to learn how to use it, I strongly advise to do so.

You may also be interested in caching forms.