Posts Tagged ‘php’

Using Zend_Form without Zend Framework MVC

Tibo BeijenMonday, December 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:

Catching PHP Exceptions: Except the unexpected

Tibo BeijenMonday, October 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…)

PHPBenelux meeting at Freshheads

Tibo BeijenWednesday, September 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…

Controlled initialization of domain objects

Tibo BeijenThursday, July 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…)

DPC09 down, DPC10 to go

Tibo BeijenSaturday, June 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…)

Explicit PHP6?

Tibo BeijenThursday, June 11th, 2009
explicit-php6

Some days ago I read Fabien Potencier’s post ‘What for PHP 6′ pointing me to some features that might be implemented in PHP6. Two of those would have been nice in a project I’m currently working on where I’ve been experimenting with ‘domain objects’ having ’scalar’ or ‘value’ objects as properties (more on that later). The first is scalar type hinting and hinted return values. The other is a __cast() method that replaces (or complements __toString()). Now that sounds quite java-ish and one of PHP merits is it’s flexibility but having the option to be more strict in my opinion is a good thing: If I feed my application with garbage I don’t blame it for being equally blunt.
(more…)

Zend_Test, Zend_Layout and the need to reset

Tibo BeijenMonday, June 1st, 2009
zend_test-zend_layout-and-the-need-to-reset

In a recent Zend Framework project I’ve used Zend_Test to test the functioning of the website ‘as a whole’. So besides testing the separate (authorization) components, the website was tested in the same way a visitor would use it. This is especially useful for testing login scenarios, so I added the test below:

public function testLogoutShouldDenyAccess()
{
    $this->login();
 
         // verify that profile page now doesn't contain login form
    $this->dispatch('/profile');
    $this->assertQueryCount('form#login', 0);
 
        // dispatch logout page
    $this->dispatch('/login/logout');
 
        // verify that profile now holds login form
    $this->dispatch('/profile');
    $this->assertQueryCount('form#login', 1);
    $this->assertNotController('profile');
}

This failed on the last assertQueryCount() which left me puzzled. Performing above steps manually seemed to work fine so I was overlooking something either in my app-code or the test-code.
(more…)

Dutch PHP Conference 2009

Tibo BeijenFriday, April 24th, 2009
dutch-php-conference-2009

Today I ordered my ticket for Dutch PHP Conference. Last year’s edition was great and this year it’s twice as long. This year I’ll skip the tutorial day though. For me the money is better spent on reading material. Anyone interested in going can save some money by registering before April 30th. My ‘usability and PHP’ paper didn’t make it but on the less PHP focused topics there is accessibility. And a lot of other interesting topics. Presentations I will probably be attending: All the Little Pieces: Distributed systems with PHP, Secure Programming with the Zend Framework and Habits of Highly Scalable Web Applications.

Linux-Fu @ phpGG

Tibo BeijenFriday, April 17th, 2009
linux-fu-phpgg

Last night there was a phpGG (dutch php user group) meeting in Utrecht with a presentation by Lorna Jane titled ‘Linux-Fu’. Attended by about 10 people, console basics & tricks were addressed. I’m not unfamiliar with Linux so the basics weren’t that new. For development I mainly use IDE’s so I just use the console to edit the occasional config file, create some symlinks, that kind of stuff. For those tasks I find myself sticking to set of commands I’ve learned and just occasionally taking the time to do an in-depth google search for better ways to get the job done. So with regard to linux shell trickery there are things to learn for me. Neat timesavers:

Switching between current and previous directory:

cd -

Going home can be done without the ~:

cd

How ‘grep’ can beat your IDE. I’ve been playing around a bit and this is really a quick way of finding all classes within a directory that implement an interface (and it’s fast!):

grep -i -r 'class ' . | grep implements

And there’s ’screen’. Very useful for handling multiple terminal sessions without the risk of losing them all due to a connection hick-up. Lorna has some config examples on her site.

So not all was new but there were definitely some nice starting points to investigate further.

Thousands of modules can’t be wrong, right?

Tibo BeijenFriday, February 20th, 2009
thousands-of-modules-cant-be-wrong-right

Yesterday I attended a presentation showcasing Drupal. Like Joomla! and Wordpress an easy install routine presents the user with a lot of functionality right out of the box. By adding modules as needed one can achieve whatever he wants. So it seems… After the showcase part, the session continued into a case study. The case at hand was a project were all sorts of specific functionality (think: facebook, digg, etc. web 2.0 you know) was required. And it didn’t go as smooth and quick as expected. How come?
(more…)