Validation
Validation answers the question of whether what the visitor sent may be saved. In Laminas the rules are described by an InputFilter: every field gets filters and validators. A filter changes the value — for example, trims spaces at the edges. A validator changes nothing; it decides whether the value is acceptable.
Rules in the form class
It is convenient to keep the rules next to the fields. Add the InputFilterProviderInterface interface and a method with the rules to the PostForm class:
// module/Blog/src/Form/PostForm.php
use Laminas\Filter\StringTrim;
use Laminas\InputFilter\InputFilterProviderInterface;
use Laminas\Validator\StringLength;
class PostForm extends Form implements InputFilterProviderInterface
{
// the constructor with the fields stays the same
public function getInputFilterSpecification(): array
{
return [
'title' => [
'required' => true,
'filters' => [
['name' => StringTrim::class],
],
'validators' => [
[
'name' => StringLength::class,
'options' => ['min' => 5, 'max' => 255],
],
],
],
];
}
}The title key is the field name. required forbids an empty value; filters and validators are lists applied in order: first all filters, then the validators.
Open /blog/add and submit the form with a two-letter title. The page opens again, an error message appears under the field, and the typed text stays in place: the action from the previous lesson already returns the form to the view script when isValid() returns false.
Rules for the second field
Add rules for the post body to the same array:
'body' => [
'required' => true,
'filters' => [
['name' => StringTrim::class],
],
],A post with an empty body can no longer be saved.
Common filters and validators
Filter (Laminas\Filter) | What it does |
|---|---|
StringTrim | Trims spaces at the edges |
StripTags | Removes HTML tags |
ToInt | Converts to an integer |
StringToLower | Converts to lower case |
Validator (Laminas\Validator) | What it checks |
|---|---|
StringLength | The string length |
EmailAddress | An email address |
Digits | Digits only |
Between | A number between min and max |
InArray | A value from the haystack list |
Identical | Equality with another field (token) |
Regex | A match against pattern |
A custom error message
The standard messages are in English. The text is replaced in the validator options:
[
'name' => StringLength::class,
'options' => [
'min' => 5,
'messages' => [
StringLength::TOO_SHORT => 'The title is shorter than 5 characters.',
],
],
],Every validator has its own message constants; they are listed at the top of its class.
Errors in the controller
All messages can be fetched as an array — for example, to write them to a log:
if (!$form->isValid()) {
$errors = $form->getMessages();
// ['title' => ['stringLengthTooShort' => 'The title is shorter than 5 characters.']]
}Validation without a form
For data that did not come from an HTML form, a set of rules alone is enough:
use Laminas\InputFilter\Factory;
use Laminas\Validator\EmailAddress;
$filter = (new Factory())->createInputFilter([
'email' => [
'required' => true,
'validators' => [['name' => EmailAddress::class]],
],
]);
$filter->setData(['email' => 'anna@example']);
if (!$filter->isValid()) {
$errors = $filter->getMessages();
}An address without a top-level domain fails the check, and $errors holds a message for the email field. The cleaned values are returned by $filter->getValues().
Common mistake
Taking data from $request->getPost() after validation is a mistake: it holds the original values, unfiltered and with any extra fields the visitor added. Save only $form->getData() — it contains just the fields described in the form, with values after the filters.