Zend Framework - Forms & Validation

Zend Framework provides a separate component, zend-form to accelerate the form creation and validation process. It connects the model and the view layer. It provides a set of form elements to create full-fledged html form from pre-defined models, an InputFilter class to validate the model against the form and options to bind the data from the form to the model and vice versa.
The Zend form component can be installed using the Composer command as specified below −
composer require zendframework/zend-form 

A Zend form framework has three subcomponents to manage the forms. They are as explained below in detail −
Elements − Used to define a single html input control mapped to a property in the model.
Elements − Used to define a single html input control mapped to a property in the model.
Fieldset − Used to group elements and other fieldset in a nested manner.
Fieldset − Used to group elements and other fieldset in a nested manner.
Form − Used to create an html form and consists of elements and fieldsets.
Form − Used to create an html form and consists of elements and fieldsets.
Zend Forms are usually created under the module//src/Form directory.
Let us now create a simple form to add book into the database. To do this, we should adhere to the following steps −
Create the “BookForm.php” under the *myapp/module/Tutorial/src/Form” directory. Add the following changes in the file −
<?php  
namespace Tutorial\Form;  
use Zend\Form\Form;  

class BookForm extends Form {
   
   public function __construct($name = null) { 
      parent::__construct('book');  
      $this->add(array( 
         'name' => 'id', 
         'type' => 'Hidden', 
      ));  
      $this->add(array( 
         'name' => 'author', 
         'type' => 'Text', 
         'options' => array( 
            'label' => 'Author', 
         ), 
      ));  
      $this->add(array( 
         'name' => 'title', 
         'type' => 'Text', 
         'options' => array( 
            'label' => 'Title', 
         ), 
      ));  
      $this->add(array( 
         'name' => 'submit', 
         'type' => 'Submit', 
         'attributes' => array( 
            'value' => 'Go', 
            'id' => 'submitbutton', 
         ), 
      )); 
   } 
}
The Form class provides an add method to map the model and its corresponding form details. we have created the BookForm by extending the Form class and added the form details for Book model.
Update the model, ‘Book’ with filter and validation as specified below −
<?php 
namespace Tutorial\Model;  
use Zend\InputFilter\InputFilterInterface; 
use Zend\InputFilter\InputFilterAwareInterface; 
use Zend\InputFilter\InputFilter;  

class Book implements InputFilterAwareInterface { 
   public $id; 
   public $author; 
   public $title;  
   protected $inputFilter;  
   public function setInputFilter(InputFilterInterface $inputFilter) { 
      throw new \Exception("Not used"); 
   }  
   public function getInputFilter() { 
      if (!$this->inputFilter) { 
         $inputFilter = new InputFilter(); 
         $inputFilter->add(array( 
            'name' => 'id', 
            'required' => true, 
            'filters' => array( 
               array('name' => 'Int'), 
            ),
         )); 
         $inputFilter->add(array( 
            'name' => 'author', 
            'required' => true, 
            'filters' => array( 
               array('name' => 'StripTags'), 
               array('name' => 'StringTrim'), 
            ), 
            'validators' => array( 
               array( 
                  'name' => 'StringLength', 
                  'options' => array( 
                     'encoding' => 'UTF-8', 
                     'min' => 1, 
                     'max' => 100, 
                  ), 
               ), 
            ), 
         )); 
         $inputFilter->add(array( 
            'name' => 'title', 
            'required' => true, 
            'filters' => array( 
               array('name' => 'StripTags'), 
               array('name' => 'StringTrim'), 
            ), 
            'validators' => array( 
               array( 
                  'name' => 'StringLength', 
                  'options' => array( 
                     'encoding' => 'UTF-8', 
                     'min' => 1, 
                     'max' => 100, 
                  ), 
               ),
            ),  
         )); 
         $this->inputFilter = $inputFilter; 
      } 
      return $this->inputFilter; 
   }  
   public function exchangeArray($data) { 
      $this->id = (!empty($data['id'])) ? $data['id'] : null; 
      $this->author = (!empty($data['author'])) ? $data['author'] : null; 
      $this->title = (!empty($data['title'])) ? $data['title'] : null; 
   } 
}
Each model should implement the InputFilterAwareInterface. The InputFilterAwareInterface provides two methods, setInputFilter() and getInputFilter().
The getInputFilter is used to get the validation details of the model. Zend framework provides a rich set of filters and validators to validate the form. Some of the filters and validators used in the book model are as follows −
StripTags − Remove unwanted HTML.
StripTags − Remove unwanted HTML.
StringTrim − Remove unnecessary white space.
StringTrim − Remove unnecessary white space.
StringLength validator − Ensure that the user does not enter more characters than the specified limit.
StringLength validator − Ensure that the user does not enter more characters than the specified limit.
Include the saveBook method to add book to the database.
BookTable.php
<?php  
namespace Tutorial\Model;  
use Zend\Db\TableGateway\TableGatewayInterface;  

class BookTable {
   protected $tableGateway; 
   public function __construct(TableGatewayInterface $tableGateway) { 
      $this->tableGateway = $tableGateway; 
   }  
   public function fetchAll() { 
      $resultSet = $this->tableGateway->select(); 
      return $resultSet; 
   }  
   public function getBook($id) { 
      $id  = (int) $id; 
      $rowset = $this->tableGateway->select(array('id' => $id)); 
      $row = $rowset->current(); 
      if (!$row) { 
         throw new \Exception("Could not find row $id"); 
      } 
      return $row; 
   }  
   public function saveBook(Book $book) { 
      $data = array ( 
         'author' => $book->author, 
         'title'  => $book->title, 
      );  
      $id = (int) $book->id; 
      if ($id == 0) { 
         $this->tableGateway->insert($data); 
      } else {
         if ($this->getBook($id)) { 
            $this->tableGateway->update($data, array('id' => $id));  
         } else { 
            throw new \Exception('Book id does not exist'); 
         } 
      } 
   } 
}
Add a new action addAction in the tutorial controller – myapp/module/Tutorial/src/Controller/TutorialController.php.
public function addAction() { 
   $form = new BookForm(); 
   $form->get('submit')->setValue('Add');  
   $request = $this->getRequest(); 
   if ($request->isPost()) { 
      $book = new Book(); 
      $form->setInputFilter($book->getInputFilter()); 
      $form->setData($request->getPost());  
      if ($form->isValid()) { 
         $book->exchangeArray($form->getData()); 
         $this->bookTable->saveBook($book);  
         
         // Redirect to list of Tutorial 
         return $this->redirect()->toRoute('tutorial'); 
      } 
   }  
   return array('form' => $form); 
}
The addAction method does the following processes −
Gets the request object.
Gets the request object.
Checks if the request's http method is a post method.
Checks if the request's http method is a post method.
If request's http method is not post, it just renders the template, add.phtml
If request's http method is not post, it just renders the template, add.phtml
If the request's http method is not post, then it sets the inputfilter, gets the request data and sets it into the inputfiler.
If the request's http method is not post, then it sets the inputfilter, gets the request data and sets it into the inputfiler.
Checks whether the form is valid using the isValid() method of Form class.
Checks whether the form is valid using the isValid() method of Form class.
If the form is not valid, it again renders the template, add.phtml
If the form is not valid, it again renders the template, add.phtml
If the form is valid, it saves the book into the database and redirects to the home page.
If the form is valid, it saves the book into the database and redirects to the home page.
Create a template – add.phtml under myapp/module/Tutorial/view/tutorial/tutorial/add.phtml
Add.phtml
<?php  
$title = 'Add new Book'; 
$this->headTitle($title);  
?>  
<h1><?php echo $this->escapeHtml($title); ?></h1>  
<?php  
if(!empty($form)) {  
   $form->setAttribute('action', $this->url('tutorial', array('action' => 'add'))); 
   $form->prepare();  
   echo $this->form()->openTag($form); 
   echo $this->formHidden($form->get('id')); 
   echo $this->formRow($form->get('author'))."<br>"; 
   echo $this->formRow($form->get('title'))."<br>"; 
   echo $this->formSubmit($form->get('submit')); 
   echo $this->form()->closeTag(); 
} 
Here, we are rendering the book form using the Form instance, $form.
Now, we can run the application – http://localhost:8080/tutorial/add.
Form Page
Validate Error Page
 Print
 Add Notes
 Bookmark this page