Managing Zend_Form in both MVC and no-MVC environments has a huge advantage, since Zend Framework comes with a load of decorators (HTML to display form fields), validators (functions to check user input) and filters (functions to filter user input). If you look for an easy way to handle all kinds of user input thru forms, ZF is the way to go… at least if you have a lot of different forms on you website, that is 😉

This articles is based on the first parts of the Star Rating series (which I still have to finish…), so it assumes you have managed to install ZF on your system, have your bootstrap.php up and running. Pls note: I changed the naming from „Mylib“ to „JD“… using my initials is easier because I can copy&paste my classes 😉 Just in case: here´s the bootstrap.php that you have to include, already with some new code:

<?php
// Define path to application directory
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', ($_SERVER['DOCUMENT_ROOT']));
// Define application environment
defined('APPLICATION_ENV')
|| define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'development'));
// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
realpath(APPLICATION_PATH . '/../library'),
get_include_path(),
)));
/**
* General PHP settings
*/
error_reporting(E_ALL|E_STRICT);
ini_set('display_errors', 1);
ini_set('default_charset', 'UTF-8');
/**
* Autoloader
*/
require_once 'Zend/Loader/Autoloader.php';
$autoloader = Zend_Loader_Autoloader::getInstance();
// Register folder library/JD/ for own classes
$autoloader->registerNamespace('JD_');
/**
* Load Zend Config from application.ini
*/
$config = new Zend_Config_Ini($_SERVER['DOCUMENT_ROOT'] . '/../library/JD/configs/application.ini', APPLICATION_ENV);
Zend_Registry::set('config', $config);
/**
* Connect to default DB
*/
$db = Zend_Db::factory($config->database);
Zend_Db_Table::setDefaultAdapter($db);
/**
* Get Zend View object (required for any view helpers, e.g. Form, Navigation)
*/
$view = new Zend_View;
$view->setEncoding('UTF-8');
$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
// Doctype for Form Renderer
$doctypeHelper = new Zend_View_Helper_Doctype();
$doctypeHelper->doctype('XHTML1_TRANSITIONAL');
/**
* Set default language for form errors etc
*/
$translate = new Zend_Translate('array', $_SERVER['DOCUMENT_ROOT'] . '/../library/JD/Languages/de.php', $config->language->default);
Zend_Form::setDefaultTranslator($translate);

In order to be able to use Zend_Form, you need to set the Zend_View, else it would not render it. The language part is optional, it´s a simple file replacing English error messages with (in this case) German ones. Refer to the ZF manual for language details.

The next part is to set some rendering options, A.K.A decorators. With most websites, I use YAML as a CSS framework, and ZF renders form elements into dt/dd tags (didn´t know anyone uses those anymore…). Anyway, re-decorating a form is a piece of cake. Create a subfolder „Form“ in your own „library“ subfolder (mine is „JD“ was „Mylib“), and create a form controller, named „Controller.php“.  If you´ve read the previous articles, you can guess the name of the class… JD_Form_Controller. Replace the „JD“ part with anything you like, according to your directory structure (e.g. „library/somename/Form/Controller“ translates to class name „somename_Form_Controller… just basic autoloading knowledge). Here´s what the controller looks like:

class JD_Form_Controller extends Zend_Form
{
// COLUMNAR YFORM decorators
// standard input type=text & textareas
protected $_standardTextDecorator = array(
'ViewHelper',
array('Label', array('escape'=>false)),
array('HtmlTag', array('tag'=>'div', 'class'=>'type-text')),
// not used
array('Description')
);
// standard input type=select
protected $_standardSelectDecorator = array(
'ViewHelper',
array('Label', array('escape'=>false)),
array('HtmlTag', array('tag'=>'div', 'class'=>'type-select')),
// not used
array('Description')
);
// standard checkbox type=checkbox
protected $_standardCheckboxDecorator = array(
'ViewHelper',
array('Label', array('escape'=>false)),
array('HtmlTag', array('tag'=>'div', 'class'=>'type-check')),
// not used
array('Description')
);
// special input type=captcha -> into type-text for styling
protected $_standardCaptchaDecorator = array(
'ViewHelper',
array('Label', array('escape'=>false)),
array('HtmlTag', array('tag'=>'div', 'class'=>'type-text')),
// not used
array('Description')
);
// standard input type=hidden w/out tags
protected $_standardHiddenDecorator = array(
'ViewHelper'
);
protected $_standardButtonDecorator = array(
'ViewHelper',
array('HtmlTag', array('class'=>'type-button'))
);
// Standard YFORM decorators
protected $_leftTextDecorator = array(
'ViewHelper',
array('Label', array('escape'=>false)),
array('HtmlTag', array('tag'=>'div', 'class'=>'type-textleft'))
);
protected $_fullTextDecorator = array(
'ViewHelper',
array('Label', array('escape'=>false)),
array('HtmlTag', array('tag'=>'div', 'class'=>'type-textfull'))
);
protected $_leftCheckDecorator = array(
'ViewHelper',
array('Label', array('escape'=>false)),
array('HtmlTag', array('tag'=>'div', 'class'=>'type-checkleft'))
);
protected $_leftButtonDecorator = array(
'ViewHelper',
array('HtmlTag', array('tag'=>'div', 'class'=>'type-buttonleft'))
);
/**
* Class constructor
*
* @param array $options
*/
public function __construct($options = null)
{        
// path setting for custom classes MUST ALWAYS be first!
$this->addElementPrefixPath('JD_Form_Decorator','JD/Form/Decorator','decorator');
$this->addElementPrefixPath('JD_Form_Validator','JD/Form/Validator','validate');
$this->addElementPrefixPath('JD_Filter','JD/Filter','filter');
parent::__construct($options);
$this->setAttrib('class', 'yform columnar');
$this->setDecorators(array(
'FormElements',
'Form'
));
}    
}

This is a lot at once, but I already set everything up for decorators (defining them and adding the prefix path), validators (still to be defined, but prefixed) and filters (also not defined yet, but prefixed). By default, I use columnar forms on the website (label next to form field: all $_standard* decorators), but also have an option to use labels above their fields ($_left or $_full). E.g. the $_standardTextDecorator wraps an INPUT element, inluding the label, into a DIV with the class „type-text“, and wraps the label into a new decorator – one that appends an * to each required input field.

Next up: Zend_Decorator and Zend_Validator