Dutch PHP Conference (DPC) 2010

Tibo BeijenJune 15th, 2010
dutch-php-conference-dpc-2010

Past weekend the Amsterdam RAI was the centre of the PHP universe as there the 2010 edition of the Dutch PHP Conference was held. Similar to past year it consisted of two presentation days, which I attended, preceded by a tutorial day.

Among the presentations I attended on the first day were:

Kevlin Henney’s keynote presentation, titled 97 Things every programmer should know. I suppose every attendant will have recognised some of the things he addressed, like “Do lots of deliberate practice” or “Hard work does not pay off”.

Design for Reusability. In this presentation Derick Rethans showed a number of concepts that can help in making code more reusable. Topics included Dependency Injection Containers, the fact that private methods can never be tested and Tie-Ins. Interesting was that Derick stated that reflection is slow whereas on day 2, in the Doctrine 2 uncon talk reflection was said to be be reasonably fast (in php 5.3 that is).

Database version control by Harrie Verveer was a very interesting talk, if only for the fact that it is a topic I’m confronted with at my day job. He showed tools like DbDeploy (and Phing), Liquibase, Doctrine Migrations and Akrabat DB Schema Manager. Especially ineresting was how branching can trouble database versioning.

Stephan Hockdoerfer’s presentation Testing untestable code showed some very unorthodox examples of how to test code that seems untestable, like replacing function names, manipulating the include path or mocking the filesystem. Interesting and besides that it’s great stuff to scare co-workers with (”look what trick I’ve learned!”).

Due to an unlucky combination of a tiresome week, a busy schedule ahead, a lot of time to kill until 20:30, and possibly age, I missed the social, so I was not devastated when day 2 started.

First presentation of day 2 was titled Security Centered Design: Exploring the Impact of Human Behaviour by Chris Shiflet. Emphasis was not on the technical aspects but on the people using an application. The presentation contained a very effective demonstration of ‘change blindness’. Quote of the presentation, and as far as I’m concerned whole DPC10: ” If you focus on the technical problem you’re missing the actual problem”

Following the keynote talk, Rob Allen covered the topic of Stress-free deployment. There was some overlap with the database versioning talk of the previous day but still a lot to learn. Especial interesting I found the part about branching, where Rob showed how branching features as well as releases can be a good solution for some pitfals concerned with release management. Not entirely in line with the branching ‘problems’ mentioned in the database versioning talk so it’s definitely a subject I’ll look into further.

After the lunch I visited the Unconference room which I didn’t regret. Jeroen Keppens opened with a short presentation on a topic we need to look into at my job in the near future: Integrating Zend_Acl and the domain layer. Short but very insightful. After two presentations about development for mobile devices (PhoneGap looks very interesting) and Cairo I decided to stay in the uncon room some more (thereby skipping the Domain NoSQL talk) as next on were two ORM-centered presentations: First Juozas Kaziukenas explained the principles of an ORM, followed by Benjamin Eberlei giving insight on Doctrine2. That looked promising yet also, after viewing the generated SQL of some of the more complex examples, spawned a very interesting discussion I had with my co-worker who visited Sebastian Bergmann’s presentation The Cake is A Lie: What problems can arise from generated code that isn’t tested and nobody is responsible for?

Concluding: Similar to past years this was a refreshing event that fuels the urge to improve by adopting new techniques and better methodologies. Besides that I really liked the Unconference initiative. Till next year!

  • Twitter
  • Reddit
  • Technorati
  • del.icio.us
  • Digg
  • StumbleUpon
  • Google Bookmarks

Zend_Form: Building dynamic forms

Tibo BeijenDecember 21st, 2009
zend_form-building-dynamic-forms

In my previous post about Zend_Form I showed how, using Zend_Form, a form’s structure can be separated from it’s presentation and how to use custom Decorators and Validators. The example used showed a form that is tightly coupled to a record in a database: One form edits one record. There are however numerous occasions where no ‘one to one’ connection exists and where the fields that need to be shown are not predetermined. Take for example a shopping cart that shows the amounts of each product. In this article I’ll take a look at how to:

  • dynamically construct a form based on the data being edited
  • use subforms to reuse common parts and group related values
  • create composite ‘elements’ by using the default Zend_Form_Element in combination with a custom decorator
  • create additional elements with Javascript and have them processed by the form when submitted

Like previous article the case examined assumes a situation where Zend_Form is used in an existing project that doesn’t use the Zend Framework MVC stack. The Form can be viewed online and all of the sample code can be found on GitHub.

Case outline

In this example I construct a form where a user can view and edit a task list for a week’s working days. Every task can be edited in one single form and new tasks can be added at will. When viewing the page the application fetches the tasks already entered for that week. The assumed codebase is able to generate and consume an array as shown below:

// array format used to supply data of multiple tasks to form
$tasks[$timestampDay1]['current'][$taskId1]['desc'] = 'Gotta do this';
$tasks[$timestampDay1]['current'][$taskId1]['completed'] = true;
$tasks[$timestampDay2]['current'][$taskId2]['desc'] = 'Gotta do that';
$tasks[$timestampDay2]['current'][$taskId2]['completed'] = false;

The ‘current’ part will later help to distinguish between new and allready stored tasks.

Dynamically building a Zend_Form

Using Zend_Form typically follows these steps:

$Form = new My_Form(); // My_Form::init() will define elements
$Form->setDefaults($myData);
if ($Form->isValid($_POST)) {
    $submittedValues = $Form->getValues();
    // process values and redirect to same or other page
}
echo $Form->render();

When a form’s elements need to be defined based on the data being edited, Zend_Form::init() is not suitable as at that point the data is not known yet. Providing data through the constructor to have it available in the init() method ‘could’ work but is not a really nice solution as it means changing the parameter scheme of the constructor. Furthermore, it would ignore the method that exists specifically for adding initial data: setDefaults(). As that will be the first point at which the form ‘knows’ what data needs to be edited, that will be the point to add elements. Or, as in this case, subforms.

My_Form_TaskWeek

The setDefaults() method of the week-form is changed as displayed below:

class My_Form_TaskWeek extends Zend_Form
{
    // ...
    public function setDefaults($defaults)
    {
        // first add the subforms
        $this->clearSubForms();
        $dates = array_keys($defaults);
        foreach ($dates as $day) {
            $dayForm = new My_SubForm_TaskDay();
            $this->addSubForm($dayForm, (string) $day);
        }
        // set defaults, which will propagate to newly created subforms
        parent::setDefaults($defaults);
    }
    // ...
}

For every day in $defaults (in this example the key is a timestamp, but it could be anything) a subform is added. This is done before calling parent::setDefaults(). With the subforms in place the call to the parent method will propagate to the subforms we’ve just created.

My_Form_TaskDay

In the form that shows one single day, some actions are performed in the init() method: A subform for both ‘current’ and ‘new’ elements is added. Also a ‘template’ element is added. The subforms have just one decorator: FormElements. The template element will be used as source for new elements that are added by javascript. When setDefaults() is called, elements are added to the current subform.

 class My_SubForm_TaskDay extends Zend_Form_SubForm
{
    // ...
   public function init() {
        // create subforms having nothing but element decorator
        $this->addSubForm(new Zend_Form_SubForm, 'current');
        $this->addSubForm(new Zend_Form_SubForm, 'new');
        $this->getSubForm('current')->setDecorators(array('FormElements'));
        $this->getSubForm('new')->setDecorators(array('FormElements'));
 
        // add template element
        $templateElement = $this->createTaskElement('__template__', array(), true);
        $this->getSubForm('new')->addElement($templateElement);
    }
 
    public function setDefaults($defaults)
    {
        $subform = $this->getSubForm('current');
        foreach ($defaults['current'] as $id => $values) {
            $subform->addElement($this->createTaskElement($id, $values));
        }
        // set defaults, which will propagate to newly created subforms & elements
        parent::setDefaults($defaults);
    }

The method that creates an element:

    protected function createTaskElement($id, $values, $isNew = false)
    {
        $elm = new Zend_Form_Element((string) $id);
        $elm->clearDecorators();
        $elm->addDecorator(new My_Decorator_TaskElement());
        $elm->addDecorator('Errors', array('placement'=>'prepend'));
 
        // add configured validator
        $validator = new My_Validator_TaskElement();
        $validator->setIsNew($isNew);
        $elm->addValidator($validator);
 
        return $elm;
    }

Creating composite elements by using custom decorator

As the code above shows, creating a task element consists of three steps:

Zend_Form_Element

A basic Zend_Form_Element is created. This is the ‘root’ class of which specific element-types (like Zend_Form_Element_Text) are descendants. The Form will supply each element with the element’s value which in this case will be an associative array with the keys ‘desc’ and ‘completed’.

My_Decorator_TaskElement

A custom decorator is added: My_Decorator_TaskElement. This decorator replaces what would normally be the ViewRenderer decorator. It is responsible for rendering both the text and checkbox input elements and wraps them in a div. For the template element (based on the element name) the containing div will be given a classname ‘template’ which will be of use when creating the javascript behaviour.

    public function render($content)
    {
        // get element details
        $elm = $this->getElement();
        $value = $elm->getValue();
        $elmName = $elm->getFullyQualifiedName();
 
        // construct inputs
        $isCompleted = isset($value['completed']) && $value['completed'];
        $descValue = (isset($value['desc'])) ? htmlspecialchars($value['desc']) : '';
 
        $inputDesc = sprintf(
            '<input type="text" name="%s" value="%s" />',
            $elmName . '[desc]',
            $descValue
        );
        $inputCompleted = sprintf(
            '<input type="checkbox" name="%s" value="1" %s />',
            $elmName . '[completed]',
            ($isCompleted) ? 'checked="checked"' : ''
        );
 
        // wrap in div, optionally adding attribute class
        $elmHtml = sprintf(
            '<div class="task %s">%s%s</div>',
            ($elm->getName() == '__template__') ? 'template' : '',
            $inputDesc,
            $inputCompleted
        );
 
        // this should be the first decorator but add the content for
        // consistency's sake
        return $content . $elmHtml;
    }

My_Validator_TaskElement

A custom validator is added: My_Validator_TaskElement (see code on GitHub). This validator will check if the description is empty but treats new elements differently from existing ones: For existing elements it is not allowed to have an empty description. For new elements this is only allowed if the ‘completed’ checkbox isn’t checked. (This way a user can still submit the form if he’d accidentally added a new field).

Using jQuery to let the user add new elements

The javascript that lets a user add a new element is implemented as a jQuery plugin. The code having the javascript initiate looks as follows:

$(document).ready(function() {
    $('form .taskDay').dynamicForm();
});

As can be seen each of the ‘day’ subforms outer elements is selected and applied upon a jQuery plugin. This plugin (on GitHub)performs the following tasks:

  • Within the element it operates on it searches for an element with classname ‘add’ and attaches a ‘click’ event handler to it.
  • It searches for an element ‘template’ and stores a reference to it.
  • Whenever the user clicks the ‘add’ button, the template element is cloned
  • Within the template element the ‘name’ attribute of any input element is altered: The string ‘__template__’ is replaced by a timestamp. This makes sure that multiple new tasks can be added within a day without them interfering with each other.
  • The new element is placed after the last found element with classname ‘task’

By referring to classnames, the javascript’s dependencies on the exact HTML are kept to a minimum. This way, if needed, the HTML structure of the form elements can be changed without the need to update the javascript.

Having the form process the new elements

When the task form is submitted, newly added tasks will be in the $_POST array as shown below:

// is assoc. array having 'desc' and 'completed' keys
$_POST[$dayTimestamp]['new'][$uniqueJSCreatedValue];

The form object needs to be able to validate the input for both the existing and the new tasks, so the $_POST array is passed to the isValid() method. At this point the form doesn’t yet contain the ‘new’ elements. Adding those is done in a similar fashion to how the existing elements are added in setDefaults(), only this time it is done in isValid(). That is the first point where the form is able to determine what the new elements are. Dynamically adding the new elements happens in the ‘day’ subform:

class My_SubForm_TaskDay extends Zend_Form_SubForm
{
    // ...
    public function isValid($data) {
        $subform = $this->getSubForm('new');
        // make sure new is array (won't be in $data if nothing submitted)
        if (!isset($data['new'])) {
            $data['new'] = array();
        }
        foreach ($data['new'] as $idx => $values) {
            // Don't add element with idx = __template__. SetIgnore works on
            // getValues. Template elements are submitted so this would otherwise
            // override the previously added template element, thereby losing the
            // setIgnore setting...
            if ($idx !== '__template__') {
                $subform->addElement($this->createTaskElement($idx, $data, true));
            }
        }
        // call parent, which will populate newly created elements.
        return parent::isValid($data);
    }
    //...
}

Here the aforementioned createTaskElement() method pops up again. Notice the third parameter (true) that will make the validator treat the element as a ‘new’ one.

All done, except for …

In theory now everything works. But practice tends to have those little things that go wrong which you hardly ever read about in code examples. When working on this example I noticed that getValues() doesn’t preserve the per-day timestamp keys in the array returned. Instead, it returns an indexed array like this:

$getValues = array(
    // this '0' should have been a timestamp, like: 1261350000
    '0' => array(
        'current' => array(), // etc. etc.
        'new' => array() // etc. etc.
    ),
    // ...
);

Bummer. As it appears, Zend_Form ‘requires’ elements, subforms and display groups to have valid variable names (See ZF-4204). One of the reasons is problably that the names also end up in HTML id attributes which are not allowed to start with a number. The name attribute is though (you can run the demo form through the W3C validator). Remarkably, the task elements, having a name consisting of the database id, are processed just fine.

Two possible solutions for this:

  • Avoid numeric names. Downside is that this also involves changing the existing code generating and processing the array. The day-form header decorator which uses the form’s name to display the date needs to be changed as well.
  • Add an implementation of getValues() in My_Form_TaskWeek that checks for numeric keys and changes them back to their original timestamp

I choose the latter (for now) because it allows to leave almost all existing code unaltered and the resulting behaviour is unit testable (supply defaults, test what is rendered, test what is returned, etc.).

Conclusion

The above shows that:

  • Subforms are very useful to repeat similar blocks within a form and to group related values in the returned value array.
  • Dynamically adding initial and newly submitted elements follows a similar pattern: Add elements based on the passed in array and then call the parent’s method. This is done in setDefaults() and isValid() respectively.

The question might arise ‘is Zend_Form the best solution for this type of customized form?’. The default ViewHelper decorator is ignored, no default validator is used. I can’t tell if Zend_Form is the best solution but fact is that it provides a lot of functionallity and flexibility: The Form, Errors and HtmlTag decorators are used ‘as is’. Furthermore, the option to reuse parts comes almost naturally because of Zend_Form’s design.

Regarding the last point I’ll conclude with following example: What if, some time after having created this form, the idea is born to have some sort of per-day dashboard page where a user can view and edit things like calendar, messages and tasks? (This is the kind of stuff that happens in agile projects). Reusing My_SubForm_TaskDay would be very useful. And luckily that is easily accomplished. All that is needed is wrapping the subform in a class that will additionally:

  • Set a view object
  • Add a submit button
  • Add a Form decorator

See the code of My_Form_TaskDay on GitHub or see it in action online.

  • Twitter
  • Reddit
  • Technorati
  • del.icio.us
  • Digg
  • StumbleUpon
  • Google Bookmarks

Using Zend_Form without Zend Framework MVC

Tibo BeijenDecember 7th, 2009
using-zend_form-without-zend-framework-mvc

Most components of Zend Framework can be used without using the entire framework and Zend_Form is no exception. It’s a versatile component that can be customized to great extent. The payoff is that seemingly easy tasks can seem quite complex to complete and involve concepts like Decorators and View Helpers. Complexity is increased by the fact that most tasks can be achieved in multiple ways.

Forms in general are elements where a lot of parts of an application ‘meet’: Frontend code (HTML/CSS), behavior (JS) and backend processing (validation, filtering and storage). In this post I’ll show how one can:

  • Use Zend_Form outside the Zend Framework MVC (most likely an existing project)
  • Separate Form rendering from it’s structure
  • Use custom validators and decorators

The Form used in this tutorial can be viewed here. The code can be browsed or downloaded on GitHub.

Zend_Form components at a glance

Let’s start with a quick look at how Zend_Form’s different components are tied together:

  • A Zend_Form consists of elements, descendants of Zend_Form_Element
  • Elements can be supplied with Validators and Filters
  • Both the form and it’s elements depend on Decorators to generate HTML. Decorators form a ‘chain’ where each decorator adds HTML to the result of the previous decorators.
  • The standard decorators provided by Zend_Form delegate the rendering of the actual HTML to View Helpers

Using Zend_Form without the MVC

As the last point above shows, Zend_Form, through Decorators, makes extensive use of Zend_View helpers. In a Zend_Framework project Zend_Form is able to retrieve the View itself. In other projects (if one wants to use any of Zend_Form’s default decorators) a View instance has to be supplied to Zend_Form:

$view = new Zend_View();
$view->doctype('XHTML1_TRANSITIONAL');
 
$form = new Zend_Form();
$form->setView(new Zend_View());

In this example the doctype is specified in the view. This controls if input elements are rendered with XHTML self-closing tags.

Separate structure and rendering

In this tutorial I create a form for an admin interface where basic user-details can be edited. Let’s assume an ACL implementation dictates that some people can actually edit the details while others are only allowed to view them. I’ve decided to keep the form definition (the ‘model’ side of a form) to a bare minimum and let different renderers (the ‘view’ side) control the output.

For re-usability and keeping controller code clean one can best create form objects by creating an instance of a subclass of Zend_Form:

class My_Form_User extends Zend_Form
{
    public function init() {
        // username
        $this->addElement('text','username', array(
            'required' => true,
            'validators' => array(
                // arguments: type, breakchain, validator constructor options
                array('Alnum', false, false),
                array('StringLength', false, array(6, 16)),
            ),
        ));
 
        // email
        $EmailValidate = new My_Validator_Email();
        $this->addElement('text','email', array(
            'required' => true,
            'validators' => array(
                array('EmailAddress', false),
                array($EmailValidate, false)
            )
        ));
 
        // ...
    }
}

(As can be seen I create an instance of My_Validate_Email and add that to the email element. We’ll look into that later. First, let’s continue with the form definition.)

The init() method is designed for this type of form definition, thereby avoiding the need to duplicate the constructor and it’s parameter scheme. As can be seen, I only define the form elements and validators. Labels and such I defer to the renderer (more on that later). As this is about integrating Zend_Form into existing projects that are not based on Zend Framework, I assume there is some sort of language-aware component. In this example I use a language pack that returns language-specific results based on tags. Adding a set of checkboxes then looks like this:

class My_Form_User extends Zend_Form
{
    public function init() {
 
        // ...
 
        $lang = new My_LanguagePack();
 
        $groupIds = array(1,2,3,4);
        $groupOptions = array();
        foreach ($groupIds as $id) {
            $groupOptions[$id] = $lang->get('group.label.' . $id);
        }
 
        $elmGroup = new Zend_Form_Element_MultiCheckbox('group');
        $elmGroup->setMultiOptions( $groupOptions );
        $elmGroup->setRequired(true);
        $this->addElement($elmGroup);
    }
}

Now I create two renderer classes for both the ‘edit’ and ‘view’ display mode. Both accepting a Zend_Form instance in the constructor. Code below shows how the form is displayed using either rendering class:

$Form = new My_Form_User();
 
$RendererEdit = new My_Form_Renderer_Edit($Form, 'user_edit');
echo $RendererEdit->render();
 
$RendererView = new My_Form_Renderer_View($Form, 'user_view');
echo $RendererView->render();

But before moving onto the renderers, let’s look into the aforementioned My_Email_Validator class.

Adding a custom validator

When specifying validators by string, as is done with ‘EmailAddress’, Zend_Form adds one of the types of Zend_Validate. For validation not covered by the standard validators one can create a custom validator by extending Zend_Validate_Abstract or implementing Zend_Validator_Interface. For email addresses, a typical scenario would be a custom validator that connects to a database and checks if the given email address is allready used by another user. For this demo I skip the database part, resulting in:

class My_Validator_Email extends Zend_Validate_Abstract
{
    protected $isValid = null;
 
    public function isValid($value) {
        $this->isValid = !in_array($value, array(
            'duplicate@test.com',
        ));
        return $this->isValid;
    }
 
    public function getMessages() {
        if ($this->isValid === false) {
            return array(
                'duplicateEmail' => 'This email address is allready used'
            );
        }
        return array();
    }
 
    public function getErrors() {
        return array_keys($this->getMessages());
    }
}

Now let’s continue with the two renderer classes:

Rendering the edit mode

The basics of the My_Form_Renderer_Edit class constructor are shown below:

class My_Form_Renderer_Edit
{
    protected $form;
 
    protected $lang;
 
    public function __construct(Zend_Form $form, $form_id = null)
    {
        $view = new Zend_View();
        $view->doctype('XHTML1_TRANSITIONAL');
 
        $this->form = $form;
        $this->form->setView(new Zend_View());
        $this->form->setAttrib('class', 'form_edit');
        if (!is_null($form_id)) {
            $this->form->setAttrib('id', $form_id);
        }
 
        $this->lang = new My_LanguagePack();
    }
 
    public function render()
    {
        // ...
}

As can be seen this is where I setup the view (as mentioned before) and set id and classname that can be used in CSS. I want the HTML to look like this:

<ul>
    <li class="">
        <div id="username-label"><label for="username" class="required">* Username</label></div>
        <div class="element">
            <input type="text" name="username" id="username" value="" class="text" />
            <span class="description">(Min 6, max 16 char.)</span>
        </div>
    </li>
</ul>

When the render() method is called on the renderer class I do four things:

  • Add a submit element
  • Setup element properties that are common for all elements
  • Setup properties on a per-element basis
  • Setup properties of the form element

I’ll briefly run through those steps. Complete code for My_Form_Renderer_Edit can be seen on Github.

Add a submit element

As long as the submit value doesn’t play a role in the processing of entered data I consider this part of the view layer. For example, interaction design might dictate that on long forms submit buttons are placed both above and below the form.

Setup common properties

By using the method setElementDecorators() of Zend_Form, all default decorators are replaced by the ones specified. The decorators that fit my needs are ViewHelper (renders the element itself) and Description, resulting in:

    protected function setupElementsCommon()
    {
         $this->form->setElementDecorators(array(
            'ViewHelper',
            array('Description', array(
                'placement' => 'append',
                'tag' => 'span',
                'class' => 'description'
            )),
         ));
    }

Setup per-element properties

Here I add additional decorators. First I setup the element’s label and description properties by using the language pack, then I add the appropriate decorators. Furthermore I add some additional classnames to elements. If the element has an error I not only want to display the errors (using a custom decorator, more on that later). I also want to give the HTML element wrapped around all of the parts an ‘error’ classname.

        $elmHasError = (count($elm->getMessages()) > 0);
        $liClass = $elmHasError ? 'error' : '';
        $elm->addDecorator(
            array('outerLi' => 'HtmlTag'),
            array('tag' => 'li', 'class' => $liClass)
        );

Setup the form object

Finally the Form is configured. After removing all existing decorators, three decorators are added. The only difference with the default set of decorators is the UL element used in the HtmlTag decorator:

    protected function setupForm()
    {
        $this->form->clearDecorators();
        $this->form->addDecorator('FormElements');
        $this->form->addDecorator('HtmlTag', array('tag' => 'ul'));
        $this->form->addDecorator('Form');
    }

Adding a custom decorator

The complete code shows that instead of the default ‘Errors’ decorator I provide my own. This way I can retrieve the error messages provided by the form element and then replace them with messages retrieved from the languagePack. A custom decorator needs to extend Zend_Form_Decorator_Abstract or implement Zend_Form_Decorator_Interface. Excerpts from My_Decorator_Errors:

    public function render($content)
        $element = $this->getElement();
        $errorMessages = $element->getMessages();
        if (empty($errorMessages)) {
            return $content;
        }
 
        // iterate over errorMessages, replace or use default
        $errorLinesHtml = '';
        foreach ($errorMessages as $errorCode => $errorMsg) {
            // make an exception for isEmpty and array representing elements
            if ($element->isArray() && $errorCode=='isEmpty') {
                $msgLangPack = $this->lang->get('form.error.array.' . $errorCode);
            } else {
                $msgLangPack = $this->lang->get('form.error.' . $errorCode);
            }
            $errorMsg = ($msgLangPack !== false) ? $msgLangPack : $errorMsg;
            $errorLinesHtml .= '<li>' . $errorMsg . '</li>';
        }
        // combine
        $errorHtml = '<ul class="errors">' . $errorLinesHtml .'</ul>';
 
        // ...

Errormessages are fetched by an element’s getMessages() method that returns an associative array. The error-codes (keys) can be used to translate the message. As can be seen I treat elements representing an array differently when fetching the ‘isEmpty’ error message.

Why using a custom errors decorator and not setting the messages on the element?

setErrors() can be used to set own errors on Zend_Form_Element. Those errors are stored in property _errorMessages which is indeed cleared first. This doesn’t remove the messages received from the validators though as they are stored in _messages. Upon adding an error by setErrors() both arrays are merged into _messages (this happens in markAsError()) and that’s the one returned by getMessages(). So trying to replace the existing isEmpty error by ’setting’ a custom error effectively adds an error instead of replacing it. getErrorMessages() does return just the new errors but… the viewHelper formErrors (which is invoked by the default ‘Errors’ decorator) uses getMessages()…

Rendering the view mode

The view renderer is a simplified version of the edit renderer. Main differences are:

  • The form doesn’t have a Form decorator and thereby no form tag. (I’ll keep calling the no-form a form though ;)).
  • All elements have only one decorator common for all elements: My_Decorator_View_Element
  • As the only element decorator doesn’t use Zend_View, the form has no need for a View element.

My_Decorator_View_Element

This decorator retrieves value and label from the element and creates. It then creates HTML making exceptions for:

  • Submit elements (which are ignored)
  • Array representing elements (where more than one value needs to be displayed)

Concluding

Above examples give an impression of how Zend_Form can be suited to virtually anyone’s needs. One can argue that separating the rendering from the basic definition adds unnecessary complexity. It does however pull HTML specifics (which during a project life-cycle often are subject to change) out of the ‘model’ layer. Both the stripped down forms and renderers are easy to reuse: The renderer can be applied to a number of forms and the forms themselves can be used in projects requiring different HTML.

Even without considering the rendering part, Zend_Form is a valuable platform offering a lot of ways to customize it. As the view renderer example shows it can also operate without Zend_View, provided one doesn’t use any of the built in decorators. Being able to provide self-built elements, validators and decorators makes it possible to use Zend_Form in virtually any project.

Further reading:

  • Twitter
  • Reddit
  • Technorati
  • del.icio.us
  • Digg
  • StumbleUpon
  • Google Bookmarks

Fronteers 2009

Tibo BeijenNovember 7th, 2009
fronteers-2009

About five months after having enjoyed server-side talks at DPC09 it was now time for front-end matters: Fronteers 2009. There’s no exaggeration in the description on the fronteers site: A stellar line up of speakers who are at the front of what’s happening in web-development. Generally speaking I really liked most of the talks and some of them pointed me to some interesting new techniques and ideas.

Slides of the presentation (if online) are listed at the Fronteers site and at the end of this post (same content, read along). I’ll briefly recap some of the (for me that is) most interesting parts.
more…

  • Twitter
  • Reddit
  • Technorati
  • del.icio.us
  • Digg
  • StumbleUpon
  • Google Bookmarks

Catching PHP Exceptions: Except the unexpected

Tibo BeijenOctober 26th, 2009
catching-php-exceptions-except-the-unexpected

PHP Exceptions can greatly assist in implementing various error scenario’s into an application. Before PHP5 one had to resort to specific return values or drastic measures like trigger_error(). Planning exceptions, I found out, is just as important as class design. At any point where a developer needs to handle the possibility of an exception being thrown he needs to know:

  • What Exceptions can I expect?
  • What Exceptions do I plan to catch?

In this post I’ll show some important aspects to consider when planning exceptions.
more…

  • Twitter
  • Reddit
  • Technorati
  • del.icio.us
  • Digg
  • StumbleUpon
  • Google Bookmarks

Usability: What does this button do?

Tibo BeijenOctober 9th, 2009
usability-what-does-this-button-do

In software development projects, paying proper attention to usability aspects, can greatly help ‘getting the message functionality across’. Usability is a field of expertise on its own and involves techniques like wireframes, prototyping and card sorting. Not every project is the same and (sadly) lack of time or budget can prevent specialized interaction designers to be involved in the project. This means that making the application ‘usable’ becomes the responsibility of graphic designers or developers (or it is neglected altogether). Not an easy combination of tasks…
more…

  • Twitter
  • Reddit
  • Technorati
  • del.icio.us
  • Digg
  • StumbleUpon
  • Google Bookmarks

PHPBenelux meeting at Freshheads

Tibo BeijenSeptember 30th, 2009
phpbenelux-meeting-at-freshheads

Yesterday (sept. 29th) I went to the Freshheads office in Tilburg to attend the monthly PHPBenelux meeting. As it appeared it was right around the corner of the 013 venue so it was an easy find.

Two talks were scheduled and Stefan Koopmanschap kicked off the meeting with a presentation titled “Integrating Symfony and Zend Framework” (slides). After a short introduction pointing out the benefits of using any framework at all, Stefan showed how both Symfony’s and Zend Framework’s autoloaders can be initialized in the application’s bootstrap code. After that using ZF components in symfony was showcased by using Zend_Service_Twitter inside a Symfony project. Being quite familiar with Zend Framework that was not really surprising (to me) but the part following was: Integrating Symfony into a Zend Framework project. First of all it was new to me that there are “Symfony Components“. Apparently Symfony is not an all-or-nothing affair anymore. Most of the components were briefly covered of which I especially found the Event Dispatcher highly interesting.

After a brief pause, Juliette Reinders Folmer hosted the big “Why Equal Doesn’t Equal Quiz”. 65 Questings testing the knowledge of the attendees about the type conversions going on when writing code like:

$a = null;
if (empty($a)) echo 'empty';
 
foreach(array('test','0','etc...') as $val) {
    if ($val) echo 'has value';
}

Questions like the ones above where the easy ones… Especially interesting where the ctype family of functions. They are especially usefull for checking database result or GPC data. Although I had seen the ctype functions before I kind of forgot about them so especially there I had wrong answers. Score: 45 out of 65.

The evening concluded with some informal chatting and some beers generously provided by Freshheads. As usual I went home with some new things on my ‘got to check that out’ list…

  • Twitter
  • Reddit
  • Technorati
  • del.icio.us
  • Digg
  • StumbleUpon
  • Google Bookmarks

Taming the Javascript event scope: Closures

Tibo BeijenJuly 27th, 2009
taming-the-javascript-event-scope-closures

When doing client-side developing there are times that jQuery’s get-this-do-that nature doesn’t provide all that is needed. For more complex applications I usually find myself creating javascript objects that ‘control’ a specific part of the page’s interaction. In the objects the application’s state is tracked, references to other objects (could be relevant DOM nodes) are stored and event handlers are set.

One of the problems typically encountered when dealing with javascript event handlers is that they have their own take on the ‘this’ keyword. Closures to the rescue.
more…

  • Twitter
  • Reddit
  • Technorati
  • del.icio.us
  • Digg
  • StumbleUpon
  • Google Bookmarks

Controlled initialization of domain objects

Tibo BeijenJuly 9th, 2009
controlled-initialization-of-domain-objects

In a recent project I’ve been working on, we have used the ‘Domain Model‘ to describe and design our application. Doing so we decouple persistency logic from the objects that are being passed around and modified throughout our application: The Domain objects. So what in MVC is often referred to as ‘model’ is actually a combination of a persistency layer, a service layer and a Domain layer. The persistency and service layer are also referred to as Data Access Objects: DAO. (As for the why and how of this architecture I recommend the article Writing robust backends with Zend Framework. For a good description of the DAO concept look here).

One of the challenges we were facing was that on one hand we wanted to implement business rules in our Domain objects. In plainish english: On setting or changing properties of the object (like changing a status) we want to validate if that action is allowed. On the other hand we want to be able to initialize an object to whatever state corresponds with the data fetched from the persistency layer. Doing so we found that the business rules got in the way during initialization when fetching it from the persistency layer. So what we were looking for was a way to allow the service layer to construct a Domain object using methods that are hidden from the rest of the code. We found two ways:

  1. Reflection (as of PHP 5.3)
  2. A design pattern where the Domain object initializes itself using the provided Service object.

more…

  • Twitter
  • Reddit
  • Technorati
  • del.icio.us
  • Digg
  • StumbleUpon
  • Google Bookmarks

DPC09 down, DPC10 to go

Tibo BeijenJune 13th, 2009
dpc09-down-dpc10-to-go

The biggest PHP event in Holland is over. Two great days have passed and it feels like it were just two hours. I didn’t attend the tutorial day so at friday after a brief intro by Cal Evans (with great cartoony visuals) the event kicked off with the opening keynote by Andrei Zmievski. A talk about what makes PHP the language it is and about where PHP is heading with 5.3 and 6. It had humor, appealing imagery and a nice metaphor comparing PHP to a ball of nails: ‘whatever you throw it at it sticks to’. For me what showed the maturity of PHP, was the fact PHP6 is undergoing (or will so) compatibility tests with respect to packages like Drupal, Wordpress and Zend Framework.
more…

  • Twitter
  • Reddit
  • Technorati
  • del.icio.us
  • Digg
  • StumbleUpon
  • Google Bookmarks