📜 ⬆️ ⬇️

Meet the Rock Validate

Data validation is one of many practices in developing a secure web application. Even a completely “young” developer, when he first becomes acquainted with the html form, tries to display a beautiful error message. What can we say about the model in some heaped framework. And therefore ...

I bring to your attention a library for data validation with customization, internationalization and other "buns". Using the well-known Respect / Validation tool with many crutches hammered in along the way, at some point I said to myself: Enough!

Tasks were set:


Everything is ugly just


$v = Validate::length(10, 20, true)->regex('/^[az]+$/i'); $v->validate('O'Reilly'); // output: false $v->getErrors(); /* output: [ 'length' => 'value must have a length between 10 and 20', 'regex' => 'value contains invalid characters' ] */ $v->getFirstError(); // output: value must have a length between 10 and 20 

The list of errors is presented in the form of an associative array.

rules


The set of rules is quite wide, because with minor changes pumped from the camp of "competitor".
')
There are groups of rules:

Full list of rules

Any additional caprice is realized by customization, or pull request.

Attribute Validation


To validate an array / object by attributes, use the attributes () method.
 $input = [ 'username' => 'O'Reilly', 'email' => 'o-reilly@site' ]; $attributes = [ 'username' => Validate::required() ->length(2, 20, true) ->regex('/^[az]+$/i'), 'email' => Validate::required()->email() ]; $v = Valiadte::attributes($attributes); $v->validate($input); // output: false $v->getErrors(); /* output: [ 'username' => [ 'regex' => 'value contains invalid characters', ], 'email' => [ 'email' => 'email must be valid', ], ] */ 

Use one set of rules for each attribute:

 Validate::attributes(Validate::required()->string())->validate($input); 

Denial of the rules


You can invert the behavior of the rules using the notOf () method. In this case, the “negative” message template Locale :: MODE_NEGATIVE is used.

 $v = Validate::notOf(Validate::required()); $v->validate(''); // output: true 

This method is applicable both for the rules of the internal attribute ['email' => Validate :: notOf (Validate :: email ())], and for all attributes as a whole. Example:

 $input = [ 'email' => 'tom@site', 'username' => '' ]; $attributes = Validate::attributes([ 'email' => Validate::email(), 'username' => Validate::required() ]); $v = Validate::notOf($attributes); $v->validate($input); // output: true 

Rule oneOf ()


If at least one rule is incorrect, then the check stops. Example:
 $input = 7; $v = Validate::oneOf(Validate::string()->email()); $v->validate($input); // output: false $v->getErrors(); /* output: [ 'string' => 'value must be string' ] */ 

For attribute validation, the script is similar to negation:
 $input = [ 'email' => 'tom@site', 'username' => '' ]; $attributes = Validate::attributes([ 'email' => Validate::email(), 'username' => Validate::required() ]); $v = Validate::oneOf($attributes); $v->validate($input); // output: false $v->getErrors(); /* output: [ 'email' => [ 'email' => 'email must be valid', ] ] */ 

When () rule


Necessary to implement the condition (ternary conditional operation). The general syntax of the method is as follows:

 v::when(v $if, v $then, v $else = null) 

Example:
 $v = Validate::when(Validate::equals('Tom'), Validate::numeric()); $v->validate('Tom'); // output false $v->getErrors(); /* output: [ 'numeric' => 'value must be numeric', ] */ 

Replacing Placeholders, Messages and Templates


Many error messages contain placeholders (for example, {{name}}), which are replaced by default values. Replace your own is not difficult:
 $v = Validate::length(10, 20) ->regex('/^[az]+$/i') ->placeholders(['name' => 'username']); $v->validate('O'Reilly'); // output: false $v->getErrors(); /* output: [ 'length' => 'username must have a length between 10 and 20', 'regex' => 'username contains invalid characters', ] */ 

Similarly, the entire message is subject to this “hot” replacement:

 $v = Validate::length(10, 20) ->regex('/^[az]+$/i') ->messages(['regex' => ',   !']); $v->validate('O'Reilly'); // output: false $v->getErrors(); /* output: [ 'length' => 'username must have a length between 10 and 20', 'regex' => ',   !' ] */ 

Depending on the arguments given in the rule method, the message template is automatically selected, but no one bothers to substitute any other that is described in the current locale. Example:

 $v = Validate::length(10, 20)->templates(['length' => Length::GREATER]); $v->validate('O'Reilly'); // output: false $v->getErrors(); /* output: [ 'length' => 'value must have a length lower than 20', ] */ 

Internationalization


Currently, there are two message dictionaries: Russian and English. By default, error messages will be displayed in English. You can set the locale via the locale () method:

 $v = Validate::locale('ru') ->length(10, 20) ->regex('/^[az]+$/i'); $v->validate('O'Reilly'); // output: false $v->getErrors(); /* output: [ 'length' => '       10  20', 'regex' => '   ', ] */ 

Customization


You can create your own rules in two steps.

Step 1. Create a class with the rule:

 use rock\validate\rules\Rule class CSRF extends Rule { public function __construct($compareTo, $compareIdentical = false, $config = []) { $this->parentConstruct($config); $this->params['compareTo'] = $compareTo; $this->params['compareIdentical'] = $compareIdentical; } public function validate($input) { if ($this->params['compareIdentical']) { return $input === $this->params['compareTo']; } return $input == $this->params['compareTo']; } } 

Step # 2. Create a class with messages:

 use rock\validate\locale\Locale; class CSRF extends Locale { const REQUIRED = 1; public function defaultTemplates() { return [ self::MODE_DEFAULT => [ self::STANDARD => '{{name}} must be valid', self::REQUIRED => '{{name}} must not be empty' ], self::MODE_NEGATIVE => [ self::STANDARD => '{{name}} must be invalid', self::REQUIRED => '{{name}} must be empty' ] ]; } public function defaultPlaceholders($compareTo) { if (empty($compareTo)) { $this->defaultTemplate = self::REQUIRED; } return [ 'name' => 'CSRF-token' ]; } } 

As previously noted, when using the notOf () rule, the message template Locale :: MODE_NEGATIVE will be substituted. The subpattern allows you to diversify messages depending on the specified arguments in the rule method. Default Locale :: STANDARD.

Profit:

 $config = [ 'rules' => [ 'csrf' => [ 'class' => \namespace\to\CSRF::className(), 'locales' => [ 'en' => \namespace\to\en\CSRF::className(), ] ], ] ]; $sessionToken = 'foo'; $requestToken = 'bar'; $v = new Validate($config); $v->csrf($sessionToken)->validate($requestToken); // output: false $v->getErrors(); /* output: [ 'csrf' => 'CSRF-token must be valid', ] */ 

Thus, it is possible to substitute the existing rules .

Additional features


There is a scenario when you need to skip the "empty" values. For example, for form fields optional to fill. For these purposes, there is a property skipEmpty - sets the reaction for each rule to "empty" values. For some rules, this property is set to false (do not skip), namely: Required, Arr, Bool, String, Int, Float, Numeric, Object, NullValue, Closure, all ctype-rules. Example:

 $v = Validate::email(); $v->validate(''); // output: true 

This behavior can be canceled:

 $v->skipEmpty(false)->validate(''); // output: false 

By default, empty values ​​are $ value === null || $ value === [] || $ value === ''. For each of the rules, it is possible to set your own isEmpty handler:

 $config = [ 'rules' => [ 'custom' => [ 'class' => \namespace\to\CustomRule::className(), 'locales' => [ 'en' => \namespace\to\en\Custom::className(), ], 'isEmpty' => function($input){ return $input === ''; } ], ] ]; $v = new Validate($config); 

Installation


 composer require romeoz/rock-validate:* 

And look?



There is a small demo that you can run with Docker :

 docker run --name demo -d -p 8080:80 romeoz/docker-rock-validate 

The demo will be available at http: // localhost: 8080 /

Source: https://habr.com/ru/post/253621/


All Articles