elie29 / validator
A library for validating a context (POST, GET etc...) by running given rules.
Installs: 8 668
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 2
Forks: 1
Open Issues: 0
Requires
- php: ^7.1
- ext-json: *
Requires (Dev)
- mockery/mockery: ^1.2
- phpstan/phpstan: ^0.12.0
- phpstan/phpstan-mockery: ^0.12.0
- phpunit/phpunit: ^7.5
- zendframework/zend-coding-standard: ^1.0
README
Introduction
A library for validating a context (POST, GET etc...) by running given rules.
Installation
Run the command below to install via Composer:
composer require elie29/validator
Getting Started
Validator
requires one or several rules (constraints) in order to validate a given context.
A basic example with $_POST
<?php use Elie\Validator\Rule\EmailRule; use Elie\Validator\Rule\MultipleAndRule; use Elie\Validator\Rule\NumericRule; use Elie\Validator\Rule\RangeRule; use Elie\Validator\Rule\StringRule; use Elie\Validator\Validator; /** * A key could have multiple rules * - name could not be empty (required and minimum 1 character length) * - age could be empty (non existent, null or '') otherwise NumericRule is applied * - age could be empty or among several values * - email is required and should be a valid string email */ $rules =[ ['name', StringRule::class, StringRule::MIN => 1, StringRule::REQUIRED => true], ['age', NumericRule::class, NumericRule::MAX => 60], ['age', RangeRule::class, RangeRule::RANGE => [30, 40, 50]], // Use composition instead of validating the key twice ['email', MultipleAndRule::class, MultipleAndRule::REQUIRED => true, MultipleAndRule::RULES => [ [StringRule::class, StringRule::MAX => 255], [EmailRule::class], ]], ]; $validator = new Validator($_POST, $rules, true); // stop processing on error. $validator->validate(); // bool depends on $_POST content
Available rules
- All Rules accept
required
,trim
andmessages
options.required
is false by default whiletrim
is true. - ArrayRule accepts
min
andmax
options. Empty value is cast to empty array []. - BicRule
- BooleanRule accepts
cast
option. - CallableRule accepts
callable
function. - ChoicesRule accepts
list
option. - CollectionRule accepts
list
andjson
options. - CompareRule accepts
sign
andexpected
options.sign
is CompareRule::EQ by default,expected
is null by default. - DateRule accepts
format
andseparator
options. - EmailRule
- IpRule accepts
flag
option. - JsonRule accepts
decode
option - MatchRule requires
pattern
option. - MultipleAndRule requires
rules
option. - MultipleOrRule requires
rules
option. - NumericRule accepts
min
,max
andcast
options. - RangeRule accepts
range
option. - StringRule accepts
min
andmax
options. - TimeRule
- Your own rule
How to add a new rule
You need to implement RuleInterface or to extend AbstractRule
<?php use Elie\Validator\Rule\AbstractRule; class MyValueRule extends AbstractRule { public const INVALID_MY_VALUE = 'invalidMyValue'; protected $my_value = null; public function __construct(string $key, $value, array $params = []) { parent::__construct($key, $value, $params); if (isset($params['my_value'])) { $this->my_value = $params['my_value']; } // + in order to add non existent key $this->messages += [ $this::INVALID_MY_VALUE => '%key%: %value% my message %my_value%' ]; } public function validate(): int { $run = parent::validate(); if ($run !== $this::CHECK) { return $run; } if ($this->value !== $this->my_value) { return $this->setAndReturnError($this::INVALID_MY_VALUE, [ '%my_value%' => $this->stringify($this->my_value) ]); } return $this::VALID; } }
Validated Context
Once validate is called, we can use validatedContext method in order to retrieve all validated values from the original context.
By default, all keys set in the rules array will be found in the validatedContext array. However, if we don't want to append non existing keys, we should call appendExistingItemsOnly(true) before validation.
Assertion Integration
Instead of using assertion key by key, you can validate the whole context and than use Assertion or Assert as follow:
<?php use Assert\Assertion; use Elie\Validator\Rule\EmailRule; use Elie\Validator\Rule\NumericRule; use Elie\Validator\Rule\StringRule; use Elie\Validator\Validator; use Webmozart\Assert\Assert; $rules =[ ['age', NumericRule::class, NumericRule::MAX => 60], ['name', StringRule::class, StringRule::MIN => 1, StringRule::REQUIRED => true], ['email', EmailRule::class, EmailRule::REQUIRED => true], ]; $validator = new Validator($_POST, $rules); Assert::true($validator->validate(), $validator->getImplodedErrors()); // OR Assertion::true($validator->validate(), $validator->getImplodedErrors());
Partial Validation
Sometimes we need to validate the context partially, whenever we have a Json item or keys that depend on each others.
The following is an example when a context - eg. $_POST - should contains a Json user data:
$rules = [ ['user', JsonRule::class, JsonRule::REQUIRED => true], ]; $validator = new Validator($_POST, $rules); Assertion::true($validator->validate()); // this assertion validates that the user is in Json format $validatedPost = $validator->getValidatedContext(); // But we need to validate user data as well (suppose it should contain name and age): $rules = [ ['name', MatchRule::class, MatchRule::PATTERN => '/^[a-z]{1,20}$/i'], ['age', NumericRule::class, NumericRule::MAX => 80], ]; $validator->setRules($rules); // Decode user as it is a valid JSON $user = json_decode($validatedPost['user'], true); $validator->setContext($user); // new context is now user data Assertion::true($validator->validate()); // this assertion validates user data /* Validate accepts a boolean argument - mergedValidatedContext - which is false by default. If set to true $validator->getValidatedContext() would return: array:4 [▼ "email" => "elie29@gmail.com" "user" => "{"name": "John", "age": 25}" "name" => "John" "age" => 25 ] */
Partial Validation with a multidimensional array
Usually with JsonRule, we could expect a multidimensional array. In this case, the validation process will be similar to Partial Validation without merging data:
$rules = [ // With Json decode, validated value will be decoded into array ['users', JsonRule::class, JsonRule::REQUIRED => true, JsonRule::DECODE => true], ]; $validator = new Validator([ 'users' => '[{"name":"John","age":25},{"name":"Brad","age":42}]' ], $rules); Assertion::true($validator->validate()); // this validate that users is a valid Json format // But we need to validate all user data as well (suppose it should contain name and age): $validator->setRules([ ['name', MatchRule::class, MatchRule::PATTERN => '/^[a-z]{1,20}$/i'], ['age', NumericRule::class, NumericRule::MAX => 80], ]); $validatedContext = $validator->getValidatedContext(); $users = $validatedContext['users']; Assertion::isArray($users); foreach ($users as $user) { // each user is a new context $validator->setContext($user); // do not merge data !! Assertion::true($validator->validate()); // we could validate all users and determine which ones are invalid! }
A new CollectionRule has been added in order to validate a collection data (array or json) as follow:
$rules = [ ['users', CollectionRule::class, CollectionRule::JSON => true, CollectionRule::RULES => [ ['name', MatchRule::class, MatchRule::PATTERN => '/^[a-z]{1,20}$/i'], ['age', NumericRule::class, NumericRule::MAX => 80], ]], ]; $data = [ 'users' => '[{"name":"John","age":25},{"name":"Brad","age":42}]' ]; $validator = new Validator($data, $rules); assertThat($validator->validate(), is(true)); $users = $validator->getValidatedContext()['users']; assertThat($users, arrayWithSize(2));
Development Prerequisites
Text file encoding
- UTF-8
Code style formatter
- Zend Framework coding standard
Composer commands
clean
: Cleans all generated filestest
: Launches unit testtest-coverage
: Launches unit test with clover.xml file generationcs-check
: For code sniffer checkcs-fix
: For code sniffer fixphpstan
: Launches PHP Static Analysis Toolcheck
: Launchesclean
,cs-check
,test
andphpstan