Over a million developers have joined DZone.

DRY'ing Up Your Zend Framework 2 Models with Annotations

DZone 's Guide to

DRY'ing Up Your Zend Framework 2 Models with Annotations

· Web Dev Zone ·
Free Resource

I’ve been using Zend Framework 2 on a recent project due to it being the department’s framework choice and off the bat one of the things that really irked me was the “Struts-ness” of how models are handled. If you walk through the ZF2 quickstart tutorial you’ll find the section on forms incredibly verbose, requiring an extra Form object and about 30 lines of boilerplate for the form’s input filter.

Luckily after digging into the documentation and source code I was able to uncover how to avoid that nonsense by using annotations. All you need as a pre-requisite is to add doctrine/common to your project (for reference, here’s my composer.json file).

    "name": "zendframework/skeleton-application",
    "description": "Skeleton Application for ZF2",
    "license": "BSD-3-Clause",
    "keywords": [
    "homepage": "http://framework.zend.com/",
    "require": {
        "php": ">=5.3.3",
        "zendframework/zendframework": "2.0.0",
    "autoload": {
      "psr-0": {

Building off the tutorial’s example, I simply delete the Form class and modify the Album model to the following.

// module/Album/src/Album/Model/Album.php:
namespace Album\Model;

use Zend\Form\Annotation as Form;

class Album{
* @Form\Required(false)
* @Form\Attributes({"type":"hidden"})
    public $id;
* @Form\Required(true)
* @Form\Attributes({"type":"text"})
* @Form\Options({"label":"Artist"})
* @Form\Filter({"name":"StringTrim"})
* @Form\Validator({"name":"StringLength", "options":{"min":1, "max":100}})
    public $artist;
* @Form\Required(true)
* @Form\Attributes({"type":"text"})
* @Form\Options({"label":"Title"})
* @Form\Filter({"name":"StringTrim"})
* @Form\Filter({"name":"StripTags"})
    public $title;

    public function exchangeArray($data){
        $this->id = (isset($data['id'])) ? $data['id'] : null;
        $this->artist = (isset($data['artist'])) ? $data['artist'] : null;
        $this->title = (isset($data['title'])) ? $data['title'] : null;

    public function getArrayCopy(){
        return get_object_vars($this);

Still looks pretty hideous but at least we’ve removed “some” of the boilerplate involved. The final step is to modify the AlbumController to use the AnnotationBuilder instead of the old AlbumForm.

 public function addAction(){
      $builder = new AnnotationBuilder();
      $form = $builder->createForm(new Album());
        'name' => 'submit',
        'attributes' => array(
            'type' => 'submit',
            'value' => 'Add',
            'id' => 'submitbutton',
      $request = $this->getRequest();
      if ($request->isPost()) {
          $album = new Album();

          if ($form->isValid()) {

              // Redirect to list of albums
              return $this->redirect()->toRoute('album');
      return array('form' => $form);

The only downside to this setup is that the submit button now feels a bit out of place. For this example I just leave it alone but I’d most likely encapsulate it somewhere. One option I’ve been playing with is to encapsulate the form generation in some kind of prototype builder but have omitted going that route for this simple example.

The changes I’ve made for this post can be found in my zend-skeleton project on github.






Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}