bus-factor / ares
Leightweight standalone validation library
Installs: 305
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 1
Forks: 0
Open Issues: 1
pkg:composer/bus-factor/ares
Requires
- php: >=7.3
- ext-json: *
- bus-factor/ddd: ^5.0
Requires (Dev)
- phpunit/phpunit: >=5.7
This package is auto-updated.
Last update: 2025-11-07 16:56:50 UTC
README
__ _ _ __ ___ ___
/ _` | '__/ _ \/ __|
| (_| | | | __/\__ \
\__,_|_| \___||___/
Ares is a lightweight standalone validation library.
Table of Contents
- Installation
- Basic Usage
- Validation Errors
- Validation Options
- Validation Rules
- Custom Types
- Custom Validation Error Messages
- Custom Validation Rules
- Sanitization
Installation
Install the library via composer:
composer require bus-factor/ares
Basic Usage
<?php use Ares\Ares; // atomic types $ares = new Ares(['type' => 'string']); $valid = $ares->validate('John Doe'); $errors = $ares->getValidationErrors(); // complex/nested types $ares = new Ares([ 'type' => 'map', 'schema' => [ 'firstName' => ['type' => 'string', 'required' => true], 'lastName' => ['type' => 'string', 'required' => true], ], ]); $valid = $ares->validate(['firstName' => 'John', 'lastName' => 'Doe']); $errors = $ares->getValidationErrors();
Validation Errors
The validate() method returns true if the provided data is valid, otherwise false.
The getValidationErrors() method returns an Ares\Validation\Error\ErrorCollection object that holds a list of Ares\Validation\Error\Error instances that are collected during the last data validation.
The list of validation errors gets reset each time validate() is called.
Each Ares\Validation\Error\Error object implements the JsonSerializable interface and contains details about the error.
The Ares\Validation\Error\ErrorCollection object is iterable but also offers 2 convenience methods:
::toArrayJsonApiStyle()- returns an array of arrays that reflects the json:api spec::toArrayNested- returns a nested array of error messages whose nested structure matches the input data's structure
Validation Options
Validation options may be passed on validation:
$schema = []; $options = []; $ares = new Ares($schema, $options);
Default validation options are:
Validator::OPTIONS_DEFAULTS = [ 'allBlankable' => false, 'allNullable' => false, 'allRequired' => true, 'allUnknownAllowed' => false, ]
allBlankable
This option applies to the type string only.
If set true, blank values are considered valid.
If set false, blank values are considered invalid.
$schema = [ 'type' => 'map', 'schema' => [ 'name' => ['type' => 'string'], ], ]; $ares = new Ares($schema); $ares->validate(['name' => ''], ['allBlankable' => true]); // -> true $ares->validate(['name' => ''], ['allBlankable' => false]); // -> false
This option may be overridden per field by using the blankable rule:
$schema = [ 'type' => 'map', 'schema' => [ 'name' => ['type' => 'string'], 'email' => ['type' => 'string', 'blankable' => true], ], ]; $ares->validate(['name' => 'John Doe', 'email' => ''], ['allBlankable' => false]); // -> true
allNullable
If set true, null is considered a valid value.
If set false, null is not considered a valid value.
$schema = [ 'type' => 'map', 'schema' => [ 'name' => ['type' => 'string'], ], ]; $ares->validate(['name' => null], ['allNullable' => true]); // -> true $ares->validate(['name' => null], ['allNullable' => false]); // -> false
This option may be overridden per field by using the nullable rule:
$schema = [ 'type' => 'map', 'schema' => [ 'name' => ['type' => 'string'], 'email' => ['type' => 'string', 'nullable' => true], ], ]; $ares->validate(['name' => 'John Doe', 'email' => null], ['allNullable' => false]); // -> true
allRequired
If set true (default) fields that are defined in the schema and not present in the input, are considered invalid.
If set false fields that are defined in the schema and not present in the input, are considered valid.
$schema = [ 'type' => 'map', 'schema' => [ 'name' => ['type' => 'string'], ], ]; $ares = new Ares($schema); $ares->validate([], ['allRequired' => true]); // -> false $ares->validate([], ['allRequired' => false]); // -> true
This option may be overridden per field by using the required rule:
$schema = [ 'type' => 'map', 'schema' => [ 'name' => ['type' => 'string'], 'email' => ['type' => 'string', 'required' => false], ], ]; $ares = new Ares($schema); $ares->validate(['name' => 'John Doe'], ['allRequired' => true]); // -> true
allUnknownAllowed
This option applies to the type map only.
If set true fields that occur in the input data but are not defined in the schema are considered invalid.
If set false fields that occur in the input data but are not defined in the schema are considered valid.
$schema = [ 'type' => 'map', 'schema' => [ 'name' => ['type' => 'string'], ], ]; $ares = new Ares($schema); $ares->validate(['name' => 'John Doe', 'initials' => 'JD'], ['allUnknownAllowed' => false]); // -> false $ares->validate(['name' => 'John Doe', 'initials' => 'JD'], ['allUnknownAllowed' => true]); // -> true
Validation Rules
allowed
The allowed validation rule checks if a value is in a given set of allowed values (enumeration).
Examples:
$ares = new Ares(['type' => 'string', 'allowed' => ['small', 'large']]); $ares->validate('medium'); // -> false $ares->validate('small'); // -> true
The allowed validation rule is the opposite of the forbidden validation rule.
blankable
The blankable rule applies to string typed values only.
If set true, blank strings are considered valid.
If set false, blank strings are considered invalid (default).
Examples:
$ares = new Ares(['type' => 'string', 'blankable' => false]); $ares->validate(''); // -> false $ares->validate(' '); // -> false $ares->validate('John Doe'); // -> true $ares = new Ares(['type' => 'string', 'blankable' => true]); $ares->validate(' '); // -> true
The blankable validation rule may be used in combination with the allBlankable validation option.
datetime
The datetime validation rule applies to string typed values only.
If set true, any parsable date/time string is considered valid.
If set false, date/time validation will not take place at all.
If set a specific date/time format string, the given value will be checked against that format too.
See DateTime::createFromFormat() for details about format strings.
Examples:
$ares = new Ares(['type' => 'string', 'datetime' => true]); $ares->validate('foo'); // -> false $ares->validate('2018-03-23'); // -> true $ares = new Ares(['type' => 'string', 'datetime' => 'd.m.Y H:i']); $ares->validate('2018-03-23'); // -> false $ares->validate('23.03.2019 00:20'); // -> true
directory
The directory validation rule checks if the given string value contains the path to an existing directory.
If set true, only paths to existing directories are considered valid.
If set false, all input is considered valid (no validation).
Examples:
$ares = new Ares(['type' => 'string', 'directory' => true]); $ares->validate(''); // -> false $ares->validate(__FILE__); // -> false $ares->validate(__DIR__); // -> true
The email validation rule checks if a value is a valid email address.
If set true, only valid email addresses are considered valid.
If set false, all input is considered valid (no validation).
Examples:
$ares = new Ares(['type' => 'string', 'email' => true]); $ares->validate('John Doe'); // -> false $ares->validate('john.doe@example.com'); // -> true
file
The file validation rule checks if the given string value contains the path to an existing file.
If set true, only paths to existing files are considered valid.
If set false, all input is considered valid (no validation).
Examples:
$ares = new Ares(['type' => 'string', 'file' => true]); $ares->validate(''); // -> false $ares->validate(__DIR__); // -> false $ares->validate(__FILE__); // -> true
forbidden
The forbidden validation rule checks if a value is in a given set of forbidden values (enumeration).
Examples:
$ares = new Ares(['type' => 'string', 'forbidden' => ['small', 'medium']]); $ares->validate('medium'); // -> false $ares->validate('large'); // -> true
The forbidden validation rule is the opposite of the allowed validation rule.
length
The length validation rule applies to string and list typed values.
The length validation rule checks if a string, or list has a specified exact length.
Examples:
$ares = new Ares(['type' => 'string', 'length' => 3]); $ares->validate('foobar'); // -> false $ares->validate('foo'); // -> true $ares = new Ares([ 'type' => 'list', 'length' => 3, 'schema' => [ 'type' => 'integer' ], ]) $ares->validate([1, 2]); // -> false $ares->validate([1, 2, 3]); // -> true
max
The max validation rule applies to float and integer typed values only.
The max validation rule checks if a value is equal to or smaller a specified maximum value.
Examples:
$ares = new Ares(['type' => 'integer', 'max' => 5]); $ares->validate(6); // -> false $ares->validate(2); // -> true
Note this validation rule will throw a Ares\Exception\InapplicableValidationRuleException when used in conjunction with non-supported value types.
maxlength
The maxlength validation rule applies to string and list typed values.
The maxlength validation rule checks if a string, or list does not exceed a specified maximum length.
Examples:
$ares = new Ares(['type' => 'string', 'maxlength' => 5]); $ares->validate('foobar'); // -> false $ares->validate('foo'); // -> true $ares = new Ares([ 'type' => 'list', 'maxlength' => 3, 'schema' => [ 'type' => 'integer' ], ]) $ares->validate([1, 2, 3, 4]); // -> false $ares->validate([1, 2, 3]); // -> true
min
The min validation rule applies to float and integer typed values only.
The min validation rule checks if a value is equal to or greater a specified minimum value.
Examples:
$ares = new Ares(['type' => 'integer', 'min' => 5]); $ares->validate(4); // -> false $ares->validate(8); // -> true
Note this validation rule will throw a Ares\Exception\InapplicableValidationRuleException when used in conjunction with non-supported value types.
minlength
The minlength validation rule applies to string and list typed values.
The minlength validation rule checks if a string, or list is not shorter than a specified minimum length.
Examples:
$ares = new Ares(['type' => 'string', 'minlength' => 5]); $ares->validate('foo'); // -> false $ares->validate('foobar'); // -> true $ares = new Ares([ 'type' => 'list', 'minlength' => 3, 'schema' => [ 'type' => 'integer' ], ]) $ares->validate([1, 2]); // -> false $ares->validate([1, 2, 3]); // -> true
nullable
If set true, null is considered a valid value.
If set false, null is considered an invalid value (default).
Examples:
$ares = new Ares(['type' => 'string', 'nullable' => false]); $ares->validate(null); // -> false $ares->validate('John Doe'); // -> true $ares = new Ares(['type' => 'string', 'nullable' => true]); $ares->validate(null); // -> true
The nullable validation rule may be used in combination with the allNullable validation option.
regex
The regex validation rule applies to string typed values only.
The regex validation rule checks if a string matches a regular expression.
Examples:
$ares = new Ares([ 'type' => 'map', 'schema' => [ 'key' => [ 'type' => 'string', 'regex' => '/^[A-Z]{3}$/', ], ], ]); $ares->validate(['key' => 'foobar']); // -> false $ares->validate(['key' => 'FOO']); // -> true
required
Use the required rule to enforce the presence of a value.
If set true, absent fields are considered invalid.
If set false, absent fields are considered valid (default).
Examples:
$ares = new Ares([ 'type' => 'map', 'schema' => [ 'name' => ['type' => 'string', 'required' => true], ], ]); $ares->validate([]); // -> false $ares->validate(['name' => 'John Doe']); // -> true
The required validation rule may be used in combination with the allRequired validation option.
schema
The schema rule is mandatory when using type list, map, or tuple.
schema (list)
The validator expects the schema to define a list item's validation rules.
Examples:
$ares = new Ares([ 'type' => 'list', 'schema' => [ 'type' => 'integer', ], ]); $ares->validate(['foo', 'bar']); // -> false $ares->validate([1, 2, 3]); // -> true
schema (map)
The validator expects the schema to define per field validation rules for associative array input.
Examples:
$ares = new Ares([ 'type' => 'map', 'schema' => [ 'email' => ['type' => 'string', 'required' => true], 'password' => ['type' => 'string', 'required' => true], ], ]); $ares->validate(['email' => 'john.doe@example.com']); // -> false $ares->validate(['email' => 'john.doe@example.com', 'password' => 'j4n3:)']); // -> true
schema (tuple)
The validator expects the schema to define validation rules per input array element. During validation input array elements are expected to be continuous indexed starting from 0 (0, 1, 2, ...).
Examples:
$ares = new Ares([ 'type' => 'tuple', 'schema' => [ ['type' => 'string', 'email' => true], ['type' => 'integer'], ], ]); $ares->validate(['john.doe@example.com']); // -> false $ares->validate([1 => 'john.doe@example.com', 2 => 23]); // -> false $ares->validate(['john.doe@example.com', 23]); // -> true
Internally, all schema elements of a tuple are required and cannot be declared optional by schema.
type
The type rule is mandatory and defines the expected/allowed value type. Supported types are:
booleanfloatintegernumeric(floatorinteger)stringmaplisttuple
Examples:
$ares = new Ares(['type' => 'float']); $ares->validate(5); // -> false $ares->validate('John Doe'); // -> false
Read the section Custom Types to find out how to define and reuse your own types.
unknownAllowed
The unknownAllowed validation rule checks if a map contains fields that are not defined in the schema.
If set true, fields that are not defined in the schema are considered valid.
If set false, fields that are not defined in the schema are considered invalid.
Examples:
$ares = new Ares([ 'type' => 'map', 'schema' => [ 'name' => ['type' => 'string'], ], 'unknownAllowed' => false, ]); $ares->validate(['name' => 'John Doe', 'email' => 'john.doe@example.com']); // -> false $ares->validate(['name' => 'John Doe']); // -> true
url
The url validation rule checks if a value is a valid URL.
Examples:
$ares = new Ares(['type' => 'string', 'url' => true]); $ares->validate('example'); // -> false $ares->validate('https://example.com'); // -> true
uuid
The uuid validation rule checks if a value is a valid UUID.
Examples:
$ares = new Ares(['type' => 'string', 'uuid' => true]); $ares->validate('example'); // -> false $ares->validate('609de7b6-0ef5-11ea-8d71-362b9e155667'); // -> true
Custom Types
Basically, a custom type is a user defined schema that is stored in and retrieved from a registry. Here's an example how it works:
use Ares\Ares; use Ares\Schema\TypeRegistry; TypeRegistry::register('GermanDateString', [ 'type' => 'string', ['datetime' => 'd.m.Y', 'message' => 'Invalid date format, try something like "24.02.2019"'], ]); TypeRegistry::register('ListOfHobbies', [ 'type' => 'list', 'schema' => [ 'type' => 'string', 'allowed' => ['Reading', 'Biking'], ], ]); TypeRegistry::register('Student', [ 'type' => 'map', 'schema' => [ 'birthDate' => ['type' => 'GermanDateString'], 'hobbies' => ['type' => 'ListOfHobbies', 'minlength' => 1], ], ]); $schema = ['type' => 'Student']; $ares = new Ares($schema); $ares->validate(['birthDate' => '1998-06-14', 'hobbies' => []]); // false $ares->validate(['birthDate' => '14.06.1998', 'hobbies' => ['Reading']]); // true
Previously registered types are unregistered using TypeRegistry::unregister().
All priviously registered types are unregistered at once using TypeRegistry::unregisterAll().
It is also possible to define recursive types.
Custom Validation Error Messages
Change the Validation Error Message of a single Rule
The following example shows how validation error messages can be customized:
// validation rule without custom message (default) $ares = new Ares([ 'type' => 'integer', ]); // validation rule with custom message $ares = new Ares([ ['type' => 'integer', 'message' => 'Pleaser provide an integer value'] ]);
Just wrap your rule (key-value) into an array and add a 'message' key.
Localization of Validation Error Messages
All built-in validation rules use the Ares\Error\ErrorMessageRendererInterface to render the messages.
If not specified, an instance of Ares\Error\ErrorMessageRenderer is created and passed to the validation process.
If necessary, a custom error message renderer can be passed to the validator:
use Ares\Ares; use Ares\Validation\Error\ErrorMessageRendererInterface; class MyErrorMessageRenderer implements ErrorMessageRendererInterface { // ... } // ... $ares = new Ares($schema); $ares->getValidator()->setErrorMessageRenderer(new MyErrorMessageRenderer()); $valid = $ares->validate($data);
Custom Validation Rules
The following simple example shows how custom validation rules are implemented and integrated:
use Ares\Ares; use Ares\Schema\Type; use Ares\Validation\Context; use Ares\Validation\RuleRegistry; use Ares\Validation\Rule\AbstractRule; class ZipCodeRule extends AbstractRule { public const ID = 'zipcode'; public const ERROR_MESSAGE = 'Invalid ZIP code'; /** * Returns all supported value types. * * @return array */ public function getSupportedTypes(): array { return [ Type::STRING, ]; } /** * Perform the value validation. * * @param mixed $args Validation rule arguments. * @param mixed $data Data being validated. * @param Context $context Validation context. * @return bool */ public function performValidation($args, $data, Context $context): bool { // implement validation ... // add error if the validation fails $context->addError(self::ID, self::ERROR_MESSAGE); // TRUE - skip all following validation rules for the current field // FALSE - run all following validation rules for the current field return false; } } RuleRegistry::register(ZipCodeRule::ID, new ZipCodeRule()); $schema = [ 'type' => 'string', 'zipcode' => true, ]; $ares = new Ares($schema);
Sanitization
This following example shows how to sanitize data:
$schema = [ 'type' => 'map', 'schema' => [ 'name' => ['type' => 'string'], 'age' => ['type' => 'integer'], 'active' => ['type' => 'boolean'], ], ]; $ares = new Ares($schema); $data = [ 'name' => ' John Doe ', 'age' => '23', 'active' => '1', 'hobby' => 'Reading', ]; $sanitizedData = $ares->sanitize($data); // Result: // [ // 'name' => 'John Doe', // 'age' => 23, // 'active' => true, // ]
As shown in the example, by default sanitization makes these adjustments:
- Trim strings
- Convert numeric strings into integer, or string values
- Convert numeric non-empty strings into boolean values
- Removes unknown fields from the input data
Sanitization Options
trimStrings
If set true (default) sorrounding whitespace will be removed from strings.
If set false sorrounding whitespace will be preserved.
purgeUnknown
If set true (default) unknown fields (fields/indices not defined in the schema) will be removed from the input data.
If set false unknown fields will be preserved.