PhpRiot
News Archive
PhpRiot Newsletter
Your Email Address:

More information

Custom Zend Framework Form Elements

Note: This article was originally published at Planet PHP on 31 July 2012.
Planet PHP

Creating forms in Zend Framework (ZF) is easy, but creating and managing complex forms can get messy! Using config files is perfectly good if you use standard Zend Form elements; it is quick and easy to setup a form in a few minutes however you will have limited control over how the form is rendered. If you want to display your own custom form element correctly in Zend Framework then some configuration is needed in order to achieve this with a config file. An alternative approach is to create some custom objects that extend the base Zend Form object - you can still use the config but also add in your own custom Zend Form elements.

If you use a custom form object then all of your form logic can be grouped together. The object can include data validation with Zend validator (and/or normal PHP validation for more complex validation routines), form data retrieval, form view format and element view rendering. This has the combined benefit of freeing the controller of any form logic needed for the custom objects and ensures the "skinny controller, fat model" approach can be used, avoiding duplicating logic as each form object is now responsible for its own data.

This article will show you how to create custom form element objects which change the standard view template for an element - the code from all the examples is available on github too, if you want to follow along. The approach shown here enables us to add logic into the element, so that the element behaves the same way in any form. A good example could be a select box that can pre-fill data from a database table and automatically add a Zend Validator to the array. We'll also cover how you can have total control over the way the form is rendered, by using a view script. As an example, we'll create an e-commerce checkout where a billing address and delivery address contain exactly the same fields with JavaScript and Zend Validation; our postcode fields will trigger a postcode lookup.

Creating a Custom Zend Form Object

Extending the Zend Form the Right Way

To gain great functionality on top of ZF, the best way is to extend the framework, creating your own base, then extend that per project, as shown in the code example below. This way if you want to add a new method to an object then you just need to add it to your own main object, leaving the core Zend object unmodified. For instance if you want every Zend Form to have a getValidatedFormData() method then you can implement it in your base class (and should Zend implement the same functionality later on then you can remove your implementation, or leave it and override theirs). Hopefully this seems obvious but I am amazed how often I see code that uses only the core Zend objects.

class MyBase_Form extends Zend_Form
{
....
}

Your main base class doesn't need to do any more than just extend the base Zend Form object; this makes it easier to update all your objects with new methods or override the core Zend methods should you need to do so in the future. The specific form (in this case Email_Form) should extend your base Zend Form object we just created, so that any and project specific-methods can be added leaving you to re-use your MyBase object.

This level of abstraction may seem slightly "over the top", however it can save you a lot of time later if more changes are needed such as changing the default display from "dt" and "dd" tags to a table layout. With the abstraction layer, this only needs to be done once and all form objects will be converted. This approach has the added benefit of easier testing as you only need to test the functionality you are actually writing.

So far, all we have done is set up a form object, now we can configure the form's elements and more importantly the validation. Using this approach we keep the validation logic together and, should the elements change, the validation can change to match. The changes are unit testable and re-useable, and validation will be also available if this form is to be used as a sub-form.

Adding the Elements

To add elements to this form, we could use a Zend_Config objects for adding standard elements only, but we get more control by adding the elements manually - so we'll do that!

class MyProject_Form_Address extends MyBase_Form
{
protected $_action_url = '/[controller]/[action]/';

public function init()
{
parent::init();
$this-setAction($this-action_url)
-setAttrib(aid', aproject_form')
-setMethod(apost');

$billing = new Zend_Form_Element_Textarea('billing_address', array(
'label' =&

Truncated by Planet PHP, read more at the original (another 16332 bytes)