Validators
Introduction
Validator class is made for quick data validation. Period.
It's primary function is to validate data on incoming request although it can validate any given key-value array. If
data is not valid, it'll throw \Koldy\Validator\Exception
.
When creating validator, you should:
- Provide key-value array where key is the parameter name and value is the rule
- Optionally provide key-value data set where key is the same key as in the first array, and value is value you want to validate.
Let's say you have a form where user needs to enter first name which is mandatory, last name which is not mandatory and age between 18 and 99. This is how you do it:
use Koldy\Validator;
$validator = Validator::only([
'first_name' => 'required|minLength:2|maxLength:40',
'last_name' => 'present|minLength:2|maxLength:40',
'age' => 'required|integer|min:18|max:99'
]);
What this actually does is:
- Validator is constructed with
only()
method which means you're validating data according to the rules you passed as first parameter - Second parameter is not defined which means that data is taken from HTTP parameters - if it's POST,
then data is taken from
$_POST
, if it's GET, data is taken from$_GET
parameters and etc. only()
will require that request contains exactly three parameters and exactly those defined - even if requested data is valid, but someone sent 4th parameter, Validator will throw an exception. If you want to validate only those three parameters and allow sending other parameters, then usecreate()
instead ofonly()
- Every parameter has it's own set of rules which can be chained using
|
If you want to manually validate some data set, simply provide data as second parameter:
$validator = Validator::create([
'first_name' => 'required|minLength:2|maxLength:40',
'last_name' => 'present|minLength:2|maxLength:40',
'age' => 'required|integer|min:18|max:99'
], [
'first_name' => 'John',
'last_name' => 'Doe',
'age' => 21
]);
If valid data is sent, you can grab values from validator by getting key-value array or stdClass
:
$array = $validator->getData(); // $array['first_name'],...
$values = $validator->getDataObj(); // returns stdClass, $values->first_name,...
If invalid data is sent, you can catch \Koldy\Validator\Exception
which contains Validator instance in which error
messages for each parameters are:
try {
$validator = Validator::only([
'first_name' => 'required|minLength:2|maxLength:40',
'last_name' => 'present|minLength:2|maxLength:40',
'age' => 'required|integer|min:18|max:99'
]);
} catch (\Koldy\Validator\Exception $e) {
print_r($e->getValidator()->getMessages());
}
Method getMessages()
will return key-value array where key is the parameter name like first_name
and value is string
which describes what is the problem. According to example, if you passed only one character for the first_name
, error
message will be Has to be at least 2 characters long
.
Beware that as soon as you use static create()
or only()
methods, Validator
will validate data and it'll throw an
exception if data is not valid. If this is not desired behaviour, you can stop validator from automatically
validating and throwing exception by passing false
as third parameter of create()
or only()
methods:
$validator = Validator::only([
'first_name' => 'required|minLength:2|maxLength:40',
'last_name' => 'present|minLength:2|maxLength:40',
'age' => 'required|integer|min:18|max:99'
], false);
if ($validator->isAllValid()) {
echo 'Good!';
print_r($validator->getData());
} else {
print_r($validator->getMessages());
}
When you chain more than one rule per parameter, please note that framework will validate data in exact order as defined
in rule. This is important if you're using exists
or unique
validators which go to database for their information.
Don't go to database if value is empty and you need it to be required.
Beware that it's usually not enough to put one rule for parameter. For example, if you put:
$validator = Validator::only([
'age' => 'min:18|max:99'
]);
It'll mean: if there's parameter age
present in data set and age
is not empty, Validator
will then check if value
is between 18-99. Failure will happen only if age
is present, not empty and not between 18-99. To forbid such
cases and to make them strict, use additional rules:
$validator = Validator::only([
'age' => 'required|integer|min:18|max:99'
]);
This example will:
- check if
age
is present in data set and not empty - if it's not, stop and fail - check if value is integer - if it's not, stop and fail
- check if value is greater than 18 - if it's not, stop and fail
- check if value is lower than 99 - if it's not, stop and fail
Available Validator Rules
This framework is shipped with set of very useful validation rules you can find on its own page: Validator Rules.
Customizing Error Messages
Framework has its own validator error messages built in which are written to be as much generic as possible so if you have your system on English, then we're sure it'll be good enough. If it's not good enough, or you want to translate error messages to other language, feel free to customize it.
All messages are stored in \Koldy\Validator\Message
class. Let's say you want to translate message This field is
required to Croatian, but including the parameter name in the message:
use Koldy\Validator\Message;
Message::setMessageString(Message::REQUIRED, 'Polje {param} je obavezno');
To test if it's good:
echo Message::getMessage(Message::REQUIRED, [
'param' => 'age'
]);
And you'll get: Polje age je obavezno.
Customizing Error Messages Dynamically
In the section above, you can see how to set error message by providing string with same basic value replacements. To
completely have different error message regarding on case, you'll have to pass Closure
:
use Koldy\Validator\Message;
Message::setMessageFunction(Message::REQUIRED, function (array $data) {
if ($data['param'] == 'age') {
return 'Age is really required field for us';
} else {
return "Field {$data['param']} is required";
}
});
Custom function always must return string.
Making Your Own Validator Rule
To make your own validator on top of existing validators, simply extend \Koldy\Validator
class and define your own
validator. Let's say you created \App\Validator
that validates quantity which will accept only integers between
10-20 and 45-150.
namespace App;
class Validator extends \Koldy\Validator {
protected function validateQuantity(string $parameter, array $args = []): ?string
{
$value = $this->getValue($parameter); // get the actual value from data set
if ($value === null) {
// act as other rules when we run on NULL
return null;
}
$value = (int)$value;
if (!(10 <= $value && $value <= 20) && !(45 <= $value && $value <= 150)) {
return 'Quantity is not between 10-20 nor 45-150';
}
return null;
}
}
And then you can use it like:
$validator = \App\Validator::only([
'product_quantity' => 'required|integer|quantity'
]);
As you can see, rules for valid values should always return null
, and when value is incorrect, rule should return
string saying what's wrong.