Getting started
Routing and controllers
Command line
Databases (SQL)
Databases (NoSQL)
Security
Packages
Learn more
- Array helper
- Caching
- Collections
- Command, event and query buses
- Date and time
- File system
- HTML helper
- Humanizer
- Image manipulation
- Internationalization
- Logging
- Number helper
- Pagination
- Retry helper
- Sessions
- String helper
- URL builder
- UUID helper
- Validation
- Views
Official packages
Validation
The mako validator provides a simple and consistent way of validating user input.
Usage
Basics
First you'll need to define a set of rules that you want to validate your input against.
$rules = [
'username' => ['required', 'min_length(4)', 'max_length(20)'],
'password' => ['required'],
'email' => ['required', 'email'],
];
The rules defined above will make sure that the username, password and email fields are present and non-empty. That the username is between 4 and 20 characters long, and that the email field contains a valid email address.
Note that most of the included validation rules will skip validation if the field is empty. The exceptions are
required
,not_empty
,one_time_token
andtoken
. You can however override this functionality by settingvalidateEmptyFields
totrue
when creating a validator instance.
Next you'll need to create a validator object. The first parameter is the input data you want to validate and the second is the set of validation rules you just defined.
$postData = $this->request->getPost();
$validator = $this->validator->create($postData->all(), $rules);
Now all that is left is to check if the input data is valid using either of the following methods: validate
, isValid
or isInvalid
.
The getValidatedInput
method returns the validated input data and throws a ValidationException
if any of the rules fail. You can retrieve the validation errors using the ValidationException::getErrors()
method.
$validatedInput = $validator->getValidatedInput();
Note that only validated input (input fields with at least one validation rule) is returned. If you have a field that doesn't require any special validation then you can use the
optional
rule to ensure that it gets returned along with the validated values.
The isValid
method returns true
if the input is valid and false
if not, while the isInvalid
method returns false
when the input validates and true
when not.
if ($validator->isValid()) {
// Do something
}
Retrieving the error messages is done using the getErrors
method
$errors = $validator->getErrors();
You can also assign it to a variable by passing it to either of the isValid
or isInvalid
methods.
if ($validator->isValid($errors)) {
// Do something
}
Nested arrays
The validator also supports nested arrays. You can assign validation rule sets to nested fields using the "dot notation" syntax.
$rules = [
'user.email' => ['required', 'email'],
];
You can also apply rule sets to multiple keys using wildcards.
$rules = [
'users.*.email' => ['email'],
];
Note that wildcard rules will only be added if the input field(s) actually exists.
Conditional rules sets
You can add rule sets to your validator instance if a certain condition is met using either the addRules
or addRulesIf
methods.
$validator->addRulesIf('state', ['required', 'valid_us_state'], function () use ($postData) {
return $postData->get('country') === 'United States of America';
});
You can also pass a boolean value instead of a closure. Rules added using either of the methods will be merged with any pre-existing rules assigned to the field.
Rules with dynamic arguments
Mako comes with a handy helper function called mako\f
that makes it easier to build rule sets that have rules with dynamic arguments. The first parameter of the function is the name of the validation rule and any subsequent arguments are treated as rule arguments.
use function mako\f;
$rules = [
'category' => ['required', f('in', $this->getCategoryIds())],
];
// The example above produces the same result as the following code
$rules = [
'category' => ['required', 'in([' . implode(',', $this->getCategoryIds()) . '])'],
];
Validation rules
The following validation rules are included with Mako:
Base rules
Name | Description |
---|---|
after | Checks that the field value is a valid date after the provided date (after("Y-m-d","2012-09-25") ). |
alpha | Checks that the field value only contains valid alpha characters. |
alpha_dash | Checks that the field value only contains valid alphanumeric, dash and underscore characters. |
alpha_dash_unicode | Checks that the field value only contains valid alphanumeric unicode, dash and underscore characters. |
alpha_unicode | Checks that the field value only contains valid alpha unicode characters. |
alphanumeric | Checks that the field value only contains valid alphanumeric characters. |
alphanumeric_unicode | Checks that the field value only contains valid alphanumeric unicode characters. |
array | Checks that the field value is an array. |
before | Checks that the field value is a valid date before the provided date (before("Y-m-d","2012-09-25") ). |
between | Checks that the field value is between x and y (between(5,10) ). |
boolean | Checks that the field contains either true or false . |
boolean:false | |
boolean:true | Checks that the field contains either true . |
date | Checks that the field value is a valid date (date("Y-m-d") ). |
different | Checks that the field value is different from the value of another field (different("old_password") ). |
Checks that the field value is a valid email address. | |
email_domain | Checks that the field value contains a valid MX record. |
enum | Checks that the field contains a valid enum value. |
exact_length | Checks that the field value is of the right length (exact_length(20) ). |
greater_than | Checks that the field value is greater than x (greater_than(5) ). |
greater_than_or_equal_to | Checks that the field value is greater than or equal to x (greater_than_or_equal_to(5) ). |
hex | Checks that the field value is valid HEX. |
in | Checks that the field value contains one of the given values (in(["foo","bar","baz"]) ). |
ip | Checks that the field value is an IP address (ip , ip("v4") or ip("v6") ). |
json | Checks that the field value contains valid JSON. |
less_than | Checks that the field value is less than x (less_than(5) ). |
less_than_or_equal_to | Checks that the field value is less than or equal to x (less_than_or_equal_to(5) ). |
match | Checks that the field value matches the value of another field (match("password_confirmation") ). |
max_length | Checks that the field value is short enough (max_length(20) ). |
min_length | Checks that the field value is long enough (min_length(10) ). |
not_empty | Checks that the field isn't empty. |
not_in | Checks that the field value does not contain one of the given values (not_in(["foo","bar","baz"]) ). |
number | Checks that the field contains an integer or float. |
number:float | Checks that the field value is a float. |
number:int | Checks that the field value is a integer. |
number:natural | Checks that the field value is a natural. |
number:natural_non_zero | Checks that the field value is a natural non zero. |
numeric | Checks that the field contains a numeric value. |
numeric:float | Checks that the field value is a float. |
numeric:int | Checks that the field value is a integer. |
numeric:natural | Checks that the field value is a natural. |
numeric:natural_non_zero | Checks that the field value is a natural non zero. |
optional | This is a special validation rule that never fails. |
regex | Checks that the field value matches a regex pattern (regex("/[a-z]+/i") ). |
required | Checks that the field exists and isn't empty. |
string | Checks that the field contains a string. |
time_zone | Checks that the field value contains a valid PHP time zone. |
url | Checks that the field value is a valid URL. |
uuid | Checks that the field value matches a valid uuid. |
Database rules
Name | Description |
---|---|
exists | Checks that the field value exist in the database (exists("users","email") ). |
unique | Checks that the field value doesn't exist in the database (unique("users","email") ). |
File rules
Basic rules
Name | Description |
---|---|
hash | Checks that the file produces the expected hash (hash("<expected_hash>") or hash("<expected_hash>", "<algorithm>") ). |
hmac | Checks that the file produces the expected hmac (hmac("<expected_hmac>", "key") or hmac("<expected_hmac>", "key", "<algorithm>") ). |
is_uploaded | Checks that the file is a successful upload. |
max_file_size | Checks that the file is smaller or equal in size to the provided limit (max_file_size("1MiB") The accepted size units are KiB , MiB , GiB , TiB , PiB , EiB , ZiB and YiB ). |
max_filename_length | Checks that the filename does not exeed the maximum allowed filename length (max_filename_length(10) ). |
mime_type | Checks that the file is of the specified mime type(s) (mime_type("image/png") or mime_type(["image/png", "image/jpeg"]) ). |
The default hash algorithm for the
hash
andhmac
rules issha256
. Any algorithm supported byhash_file
can be used.
The
max_file_size
andmax_filename_length
rules expectSplFileInfo
,FileInfo
orUploadedFile
objects.The
hash
,hmac
, andmime type
rules expectFileInfo
orUploadedFile
objects.The
is_uploaded
rule expectsUploadedFile
objects.
Image rules
Name | Description |
---|---|
aspect_ratio | Checks that the image matches the expected aspect ratio (aspect_ratio(4, 3) ). |
exact_dimensions | Checks that the image matches the expected dimensions (exact_dimensions(800, 600) ). |
max_dimensions | Check that the image is smaller than or equal to the max dimensions (max_dimensions(800, 600) ). |
min_dimensions | Check that the image is larger than or equal to the min dimensions (min_dimensions(800, 600) ). |
The image validation rules expect
SplFileInfo
,FileInfo
orUploadedFile
objects.
The rules use the
getimagesize
function to get the image size. You should make sure that the file you're validating is an image using themime type
rule before using any of the image specific rules.
Session rules
Name | Description |
---|---|
one_time_token | Checks that the field value matches a valid session one time token. |
token | Checks that the field value matches a valid session token. |
Custom messages
All error messages are defined in the app/i18n/*/strings/validate.php
language file.
Adding custom field specific error messages can be done using the overrides.messages
array:
'overrides' =>
[
'messages' =>
[
'username' =>
[
'required' => 'You need a username!',
],
],
],
You can also add custom field name translations using the overrides.fieldnames
array:
'overrides' =>
[
'fieldnames' =>
[
'email' => 'email address',
],
],
Custom rules
You can, of course, create your own custom validator rules. All rules must implement the RuleInterface
interface.
<?php
use mako\validator\rules\RuleInterface;
/**
* Is foo validation rule.
*/
class IsFooRule implements RuleInterface
{
/**
* {@inheritdoc}
*/
public function validateWhenEmpty(): bool
{
return false;
}
/**
* {@inheritdoc}
*/
public function validate($value, string $field, array $input): bool
{
return mb_strtolower($value) === 'foo';
}
/**
* {@inheritdoc}
*/
public function getErrorMessage(string $field): string
{
return sprintf('The value of the %1$s field must be "foo".', $field);
}
}
If you want it to return error messages from a language file then you'll have to implement the I18nAwareInterface
interface.
Note that there is a reusable trait (
I18nAwareTrait
) that implements the interface so that you don't have to write the code yourself.
You can register your custom rules with the validation factory, thus making it available to all future validator instances.
$this->validator->extend('is_foo', IsFooRule::class);
You can also register it into an existing validator instance.
$validator->extend('is_foo', IsFooRule::class);
Or you can just use the class name when setting up your input validation.
$rules = [
'foo' => ['required', IsFooRule::class],
];
Prefix the rule name with your package name and two colons (
::
) if your validator is a part of a package to avoid naming collisions.
Input validation in controllers
Mako includes a middleware and a trait that will greatly reduce the ammount of boilerplate code that you need to write to validate user input in controllers.
The middleware will catch ValidationException
exceptions and convert them to a Bad Request
response where the response body will be delivered as HTML, JSON or XML based on the request context.
The trait includes two helpful methods, getValidatedInput
and getValidatedFiles
, that will allow you to validate user input as well as uploaded files.
<?php
namespace app\http\controllers;
use mako\http\routing\attributes\Middleware;
use mako\http\routing\Controller;
use mako\validator\input\http\routing\middleware\InputValidation;
use mako\validator\input\http\routing\traits\InputValidationTrait;
class Article extends Controller
{
use InputValidationTrait;
#[Middleware(InputValidation::class)]
public function store(): void
{
$input = $this->getValidatedInput([
'title' => ['required', 'min_length(1)', 'max_length(255)'],
'body' => ['required', 'min_length(1)', 'max_length(64000)'],
]);
// Do something with the input ...
}
}
Note that the two methods only return validated input (input fields with at least one validation rule). If you have a field that doesn't require any special validation then you can use the
optional
rule to ensure that it gets returned along with the validated values.