Validation
, (*1)
, (*2)
Installation
If you are working on an Asgard project you don't need to install this library as it is already part of the standard libraries., (*3)
composer require asgard/validation 0.*
, (*4)
Validator
Usage in the Asgard Framework
#rulesRegistry instance
$rulesRegistry = $container['rulesRegistry'];
#validator instance
$validator = $container->make('validator');
The container is often accessible as a method parameter or through a ContainerAware object. You can also use the singleton but it is not recommended., (*5)
Usage outside the Asgard Framework
use Asgard\Validation\Validator;
use Asgard\Validation\RulesRegistry;
$rulesRegistry = new RulesRegistry();
$validator = new Validator();
$validator->setRegistry($rulesRegistry);
Instantiating the rulesRegistry is optional. If not, the validator will automatically use the RulesRegistry singleton., (*6)
Adding rules
$validator->rule('min', 5);
Multiple parameters:, (*7)
$validator->rule('between', [5, 10]);
Adding multiple rules at once:, (*8)
$validator->rules([
'min' => 5,
'max' => 10,
]);
If you do not give any parameter, it defaults to true, for example:, (*9)
$validator->rules(['required']);
#or chaining:
$validator->min(5)->max(10);
You can also initialize the validator with static calls:, (*10)
Validator::min(5)->max(10); #returns object Validator
Validating attributes
Sometimes you validate arrays and need to use specific rules for some attributes., (*11)
Adding multiple rules at once for an attribute:, (*12)
$validator->attribute('attr', ['min' => 5, 'max' => 10]);
#chaining:
$validator->attribute('attr')->min(5)->max(10);
Using a new validator for an attribute:, (*13)
$v = Validator::min(5)->max(10);
$validator->attribute('attr', $v)
For a nested attribute, use dots:, (*14)
$validator->attribute('attr.subattr.subsubattr', ['min' => 5, 'max' => 10]);
$validator->valid(['attr'=>['subattr'=>['subsubattr'=>7]]]); #returns true
Validator::min(5)->valid(3); #returns false, below 5
Validator::min(5)->valid(7); #returns true, above 5
With attributes:, (*15)
$v = $validator->attribute('attr')->min(5);
$v->valid(['attr'=>2]); #returns false
$v->valid(['attr'=>7]); #returns true
Validation groups
$validator->rule('min', [5, 'groups'=>['default', 'registration']]);
$validator->valid(6, ['registration']);
By default, if the groups are not specified, rules belong to the "default" group only., (*16)
If you want to validate all elements of an array:, (*17)
Validator::ruleEach('min', 5)->valid([4,5,6,7,8]); #returns false because of 4
By using rule instead of ruleEach, it would try to compare the array itself with 5., (*18)
Short syntax
Validator::rule('lengthbetween:1,3|contains:c')->valid('ac'); #returns true
Validator::rule('lengthbetween:1,3|contains:c')->valid('aaaaac'); #returns false
Validator::rule('lengthbetween:1,3|contains:c')->valid('aa'); #returns false
Throwing exceptions
Validator::min(5)->assert(3); #throws \Asgard\Validation\ValidatorException
You can access the errors through:, (*19)
try {
Validator::min(5)->assert(3);
} catch(\Asgard\Validation\ValidatorException $e) {
$e->errors(); #returns a Asgard\Validation\ValidatorException object
}
To make an input required, use the rule "required":, (*20)
Validation::required()->valid(null) #returns false
Validation::required()->valid(5) #returns true
And this will return true:, (*21)
Validation::equal('123')->valid(null) #returns true
Validation::equal('123')->valid('') #returns true
Because if the input is empty and not required, it is not be checked against any rule., (*22)
However you may sometimes consider other types of inputs as empty. For example an empty array. In order to do that, use isNull:, (*23)
Validation::isNull(function($arr) { return count($arr)==0; })->valid([]); #returns true, because the input is empty and not required
Validation::contains(1)->valid([]); #returns false
Sometimes the requirement depends on conditions. For example, a payment may be required if the amount is over 400., (*24)
$v->attribute('payment', ['required' => function($input, $parent, $validator) {
return $parent->attribute('amount') >= 400;
}]);
$v->valid(['amount'=>300]); #true
$v->valid(['amount'=>500]); #false
Getting the error report
$report = Validator::min(5)->errors(3); #returns a report (Asgard\Validation\ValidatorException)
You can also get errors specific to some validation groups:, (*25)
$validator->rule('min', [5, 'groups'=>['default']]);
$validator->rule('min', [10, 'groups'=>['payment']]);
$validator->errors(7, ['payment']);
Adding parameters to the validator
$v->set('form', $form);
You can access the parameter in the rule function:, (*26)
//...
public function validate($input, \Asgard\Validation\InputBag $parentInput, \Asgard\Validation\Validator $validator) {
$form = $validator->get('form');
//...
}
//...
If an attribute validator does not have a parameter, it will ask its parents., (*27)
, (*28)
Error report
Error reports contain error messages for all rules or attributes that failed. Attributes included in a report have their own nested report., (*29)
To get all error messages of a report (without nested ones):, (*30)
$errors = $report->errors();
To get the main error message:, (*31)
$error = $report->error();
To get the error message of a specific rule:, (*32)
$error = $report->error('min');
To get the first message error of an attribute:, (*33)
$attrError = $report->first('attr');
To get a list of attributes that failed:, (*34)
$failed = $report->failed();
To navigate through the report:, (*35)
$r = $report->attribute('attr'); #returns the attribute report
$r->errors(); #returns all its errors
$r->error('min'); #returns specific rule error
In case you need to build your own report from differences sources, set an attribute report:, (*36)
$attrReport = new Report(['min' => 'attr is to high.']);
$report->attribute('attr', $attrReport);
To get all nested attributes reports:, (*37)
$errors = $report->attributes();
To check if a report has any error:, (*38)
$report->hasError(); #returns true or false
If a validator has multiple rules with the same name, the report will add an increasing integer to each name:, (*39)
Validator::contains('a')->contains('b')->errors('c')->errors();
# returns
[
'contains' => '"c" must contain "a".',
'contains-1' => '"c" must contain "b".',
]
To access a nested attribute, use dots:, (*40)
$report->attribute('attr.substtr.subsubsttr')
, (*41)
Error messages
Custom messages
You can specify one or multiple messages for a validator rules:, (*42)
$validator->ruleMessages([
'min' => 'Must be over :min!',
'max' => 'Must be below :max!',
]);
#or
$validator->ruleMessage('min', 'Must be over :min!');
Or specify a message for rules in the RulesRegitry:, (*43)
$registry->messages([
'min' => 'Must be over :min!',
'max' => 'Must be below :max!',
]);
#or
$registry->message('min', 'Must be over :min!');
If you did not do any of the two above, the validator will take the default rule message by calling the method getMessage() of the rule:, (*44)
public function getMessage() {
return ':attribute must be greater than :min.';
}
If the rule does not have a its own message, the validator will get the default message error that you can set with:, (*45)
$validator->setDefaultMessage(':attribute is wrong!');
Finally, if any of the above is available, it will return the message: ":attribute is not valid.", (*46)
Message parameters
As you have seen, messages have parameters like :attribute, :input, etc., (*47)
- The parameter :attribute is either the name of the attribute or the input itself.
- The parameter :input is available when the input is a string or numeric.
Then comes rules specific parameters. Any rule with member variables, can use them as parameters in the error message. For example the rule Asgard\Validation\Rule\Min has a variable "min". Hence, you can use the parameter :min in its message: ":attribute must be greater than :min.", (*48)
, (*49)
All rules receive the raw input and the parent input bag. You can use the input bag object to navigate through the whole input:, (*50)
//...
public function validate($input, \Asgard\Validation\InputBag $parentInput, \Asgard\Validation\Validator $validator) {
return $input == $parentInput->attribute('^.confirm')->input();
}
//..
The sign ^ is used to go to the parent, and go down the tree with the list of attributes separated with a dot.
For example, with the input ['password'=>'abc', 'confirm'=>'zyx'], and validating attribute "password", the previous function will access to the value of the "confirm" attribute., (*51)
You can check that an attribute exists with:, (*52)
$parentInput->hasAttribute('^.confirm');
, (*53)
Rules
Creating new rules
You can create new rules through the rulesregistry. Either use the default instance or a new instance:, (*54)
$rr = RulesRegistry::instance();
or, (*55)
$rr = new RulesRegistry();
$validator = new Validator();
$validator->setRegistry($rr);
If a validator doesn't haven its own rulesregistry, it will ask its parent, like here:, (*56)
$validator->attribute('attr', Validator::min(5));
The attribute validator will ask the main validator for the rulesregistry. If the parent doesn't have one, it will use the default RulesRegistry instance., (*57)
Registering new rules
$rr->register('customrule', function($input) { /*...*/ });
$rr->register('customrule', 'Namespace\Rule\Customrule');
$rr->register('customrule', new \Namespace\Rule\Customrule(/* params */));
Registering namespaces
Let's say you want to add multiple rules, all in the same namespace. You can do:, (*58)
$rr->registerNamespace('Namespace\Rules');
When looking for a rule (like "customrule"), the rulesregistry will check if the class Namespace\Rule\Customrule exists., (*59)
If a rule is not found, it will throw an exception., (*60)
List of existing rules
All: must validate all validators passed as parameters, (*61)
Validator::all(v::contains('a'), v::contains('b'));
Allin: check that all elements of an array are in another array, (*62)
Validator::allin([1,2,3,4,5]);
Any: must validate any of the rules passed as parameters, (*63)
Validator::any(v::contains('a'), v::contains('b'));
Callback: use a custom rule in a lambda function, (*64)
Validator::callback(function($input) { return $input == 5; });
#or
Validator::rule(function($input) { return $input == 5; })
Contains: the string input must contain the substring passed as parameter, (*65)
Validator::contains('a')
Date: must be a valid date (xxxx-xx-xx), (*66)
Validator::date()
Each: each attribute of the input must be valid with the validator passed as parameter, (*67)
Validator::each(v::min(5))->valid([4, 5, 6, 7]) #returns false because of 4
Email: the input must be an email address, (*68)
Validator::email()
Equal: the input must be equal to the value passed as parameter, (*69)
Validator::equal(12345)
Haslessthan: the input must be have less elements than specified, (*70)
Validator::haslessthan(5)
Hasmorethan: the input must have more elements than specified, (*71)
Validator::hasmorethan(5)
In: the input must be in the given array, (*72)
Validator::in([1,2,4,5])
Int: the input must be an integer, (*73)
Validator::int()
Isinstanceof: the input must be an instance of.., (*74)
Validator::isinstanceof('Namespace\Class')
Length: the input must have "length" characters., (*75)
Validator::length(10)
Lengthbetween: the input length must be between min and max, (*76)
Validator:lengthbetween(10, 20)
Minlength: the input length must be greater than specified or equal, (*77)
Validator:minlength(10)
Maxlength: the input length must be less than specified or equal, (*78)
Validator:maxlength(10)
Min: the input must be greater than min, (*79)
Validator::min(5)
Max: the input must be less than max, (*80)
Validator::max(10)
Regex: the input must match the given pattern, (*81)
Validator::regex('/^[a-z]+$/')
Required, (*82)
Validator::required()
Same: the input attribute must be equal to another attribute, (*83)
Validator::same('^.confirm')
Contributing
Please submit all issues and pull requests to the asgardphp/asgard repository., (*84)
License
The Asgard framework is open-sourced software licensed under the MIT license, (*85)