A validation library for PHP that uses the notification pattern.
- PHP 8.2 - 8.5
composer require selective/validation
A notification is a collection of errors
In order to use a notification, you have to create the ValidationResult object. A ValidationResult can be really
simple:
<?php use Selective\Validation\Exception\ValidationException; use Selective\Validation\ValidationResult; $validationResult = new ValidationResult(); if (empty($data['username'])) { $validationResult->addError('username', 'Input required'); }
You can now test the ValidationResult and throw an exception if it contains errors.
<?php if ($validationResult->fails()) { throw new ValidationException('Please check your input', $validationResult); }
Login example:
<?php use Selective\Validation\Exception\ValidationException; use Selective\Validation\ValidationResult; // ... // Get all POST values $data = (array)$request->getParsedBody(); $validation = new ValidationResult(); // Validate username if (empty($data['username'])) { $validation->addError('username', 'Input required'); } // Validate password if (empty($data['password'])) { $validation->addError('password', 'Input required'); } // Check validation result if ($validation->fails()) { // Trigger error response (see validation middleware) throw new ValidationException('Please check your input', $validation); }
Validating a JSON request works like validating form data, because in PHP it's just an array from the request object.
<?php use Selective\Validation\ValidationResult; // Fetch json data from request as array $jsonData = (array)$request->getParsedBody(); $validation = new ValidationResult(); // ... if ($validation->fails()) { throw new ValidationException('Please check your input', $validation); }
In vanilla PHP you can fetch the JSON request as follows:
<?php $jsonData = (array)json_decode(file_get_contents('php://input'), true); // ...
The Selective\Validation\Regex\ValidationRegex class allows you to validate if
a given string conforms a defined regular expression.
Example usage:
use Selective\Validation\Factory\CakeValidationFactory; use Selective\Validation\Regex\ValidationRegex; // ... $data = [ /* ... */ ]; $validationFactory = new CakeValidationFactory(); $validator = $validationFactory->createValidator(); $validator ->regex('id', ValidationRegex::ID, 'Invalid') ->regex('country', ValidationRegex::COUNTRY_ISO_2, 'Invalid country') ->regex('date_of_birth', ValidationRegex::DATE_DMY, 'Invalid date format');
The ValidationExceptionMiddleware catches the ValidationException and converts it into a nice JSON response.
Insert a container definition for ValidationExceptionMiddleware::class:
<?php use Psr\Container\ContainerInterface; use Psr\Http\Message\ResponseFactoryInterface; use Selective\Validation\Encoder\JsonEncoder; use Selective\Validation\Middleware\ValidationExceptionMiddleware; use Selective\Validation\Transformer\ErrorDetailsResultTransformer; use Slim\App; use Slim\Factory\AppFactory; // ... return [ ValidationExceptionMiddleware::class => function (ContainerInterface $container) { $factory = $container->get(ResponseFactoryInterface::class); return new ValidationExceptionMiddleware( $factory, new ErrorDetailsResultTransformer(), new JsonEncoder() ); }, ResponseFactoryInterface::class => function (ContainerInterface $container) { $app = $container->get(App::class); return $app->getResponseFactory(); }, App::class => function (ContainerInterface $container) { AppFactory::setContainer($container); return AppFactory::create(); }, // ... ];
Add the ValidationExceptionMiddleware into your middleware stack:
<?php use Selective\Validation\Middleware\ValidationExceptionMiddleware; use Slim\Factory\AppFactory; require_once __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); // ... $app->add(ValidationExceptionMiddleware::class); // ... $app->run();
<?php use Selective\Validation\ValidationException; use Selective\Validation\ValidationResult; $validation = new ValidationResult(); // Validate username if (empty($data->username)) { $validation->addError('username', 'Input required'); } // Check validation result if ($validation->fails()) { // Trigger the validation middleware throw new ValidationException('Please check your input', $validation); }
You can combine this library with a validator that is doing the actual validation of your input data.
The converter pattern makes it easy to map instances of one class into instances of another class.
The cakephp/validation library provides features to build validators that can validate arbitrary arrays of data with ease.
Installation
composer require cakephp/validation
Usage
The Cake\Validation\Validator::validate() method returns a non-empty array when
there are validation failures. The list of errors then can be converted into
a ValidationResult using the Selective\Validation\Factory\CakeValidationFactory
or Selective\Validation\Converter\CakeValidationConverter.
For example, if you want to validate a login form you could do the following:
use Selective\Validation\Factory\CakeValidationFactory; use Selective\Validation\Exception\ValidationException; // ... // Within the Action class: fetch the request data, e.g. from a JSON request $data = (array)$request->getParsedBody(); // Within the Application Service class: Do the validation $validationFactory = new CakeValidationFactory(); $validator = $validationFactory->createValidator(); $validator ->notEmptyString('username', 'Input required') ->notEmptyString('password', 'Input required'); $validationResult = $validationFactory->createValidationResult( $validator->validate($data) ); if ($validationResult->fails()) { throw new ValidationException('Please check your input', $validationResult); }
Please note: The CakeValidationFactory should be injected via constructor.
Read more: https://odan.github.io/2020/10/18/slim4-cakephp-validation.html
If you want to implement a custom response data structure,
you can implement a custom transformer against the
\Selective\Validation\Transformer\ResultTransformerInterface interface.
Example
<?php namespace App\Transformer; use Selective\Validation\Exception\ValidationException; use Selective\Validation\Transformer\ResultTransformerInterface; use Selective\Validation\ValidationResult; final class MyValidationTransformer implements ResultTransformerInterface { public function transform( ValidationResult $validationResult, ValidationException $exception = null ): array { // Implement your own data structure for the response // ... return []; } }
The MIT License (MIT). Please see License File for more information.