Forms
A form in Laminas is an object. Its class lists the fields, and a view script renders them with ready-made helpers. The controller hands the submitted data to the form and takes it back already processed. The laminas-form package does this; form classes live in module/<Module>/src/Form.
Installation
composer require laminas/laminas-formThe installer offers to inject the Laminas\Form module and a few related ones into config/modules.config.php — accept them all.
The form class
Create the file by hand:
// module/Blog/src/Form/PostForm.php
namespace Blog\Form;
use Laminas\Form\Element;
use Laminas\Form\Form;
class PostForm extends Form
{
public function __construct()
{
parent::__construct('post');
$this->add([
'name' => 'title',
'type' => Element\Text::class,
'options' => ['label' => 'Title'],
]);
$this->add([
'name' => 'body',
'type' => Element\Textarea::class,
'options' => ['label' => 'Text'],
]);
$this->add([
'name' => 'submit',
'type' => Element\Submit::class,
'attributes' => ['value' => 'Save'],
]);
}
}Each add() call adds one field: name is the field name, type the element class, options.label the label and attributes the HTML attributes.
| Element | What it renders |
|---|---|
Element\Text | A single-line field |
Element\Textarea | A multi-line field |
Element\Email, Element\Password | Email and password fields |
Element\Select | A drop-down list |
Element\Checkbox | A checkbox |
Element\Submit | A submit button |
Showing the form
The action creates the form and passes it to the view script:
// module/Blog/src/Controller/PostController.php
use Blog\Form\PostForm;
public function addAction()
{
$form = new PostForm();
return new ViewModel(['form' => $form]);
}The view script renders the form piece by piece:
<!-- module/Blog/view/blog/post/add.phtml -->
<h1>New post</h1>
<?php $form = $this->form; ?>
<?php $form->prepare(); ?>
<?= $this->form()->openTag($form) ?>
<?= $this->formRow($form->get('title')) ?>
<?= $this->formRow($form->get('body')) ?>
<?= $this->formSubmit($form->get('submit')) ?>
<?= $this->form()->closeTag() ?>openTag() prints the opening form tag with the POST method, formRow() prints the label, the field and its errors. Open /blog/add — the page shows two fields and a button.
Handling
Extend the action: on submit the form receives the data, validates it and gives it back.
use Blog\Model\Post;
public function addAction()
{
$form = new PostForm();
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$post = new Post();
$post->exchangeArray($form->getData());
$this->posts->save($post);
return $this->redirect()->toRoute('blog/view', ['id' => $post->id]);
}
}
return new ViewModel(['form' => $form]);
}Fill in the form and press "Save": the post goes into the posts table and the browser opens its page. While there are no validation rules, isValid() accepts any data — the next lesson adds the rules.
Editing a post
In the edit action the form is first filled with values from the database:
$form->setData(['title' => $post->title, 'body' => $post->body]);The fields appear with the post's text already in them. On submit the order is the same: setData(), isValid(), getData(), save().
Common mistake
getData() may be called only after isValid(). If you call it earlier, Laminas throws an exception saying the form has not been validated yet. The order is always the same: setData(), then isValid(), then getData().