moccalotto/valit

Validate http requests, input-data and method arguments at runtime using self-documenting code

2.1.1 2018-12-26 09:25 UTC

README

Travis Build Status PHP Versions Latest Stable Version License

Validate variables using a fluent syntax.

Installation

Execute the following composer command in your terminal:

composer require moccalotto/valit

Usage

Ensure::that($age)
    ->isNumeric()
    ->isGreaterThanOrEqual(18)
    ->isLowerThanOrEqual(75);

The example above uses the Valit\Ensure facade to validate a variable. If any of the assertions fail, a Valit\Exceptions\InvalidValueException is thrown.

Validating values

If you don't want exceptions to be thrown, use the Check facade.

You can use the throwExceptionIfNotSuccessful method to throw an exception if one or more assertions fail. The advantage of this is that the exception thrown will contain all the failed assertions, not just the first one.

use Valit\Check;

$age = 42; // the variable to validate

$validation = Check::that($age)
    ->isInt()                   // Success
    ->isGreaterThanOrEqual(42)  // Success
    ->isLessThan(100);          // Success

$validation->throwExceptionIfNotSuccessful();

// no exception cast, we continue

See also:

Validating containers

You can easily test an entire array, for instance posted fields or a json response, in a structured and well defined way like the example below:

$checks = Check::that($input)->contains([
    'name'      => 'string & shorterThan(100)',
    'email'     => 'email & shorterThan(255)',
    'address'   => 'string',
    'age'       => 'naturalNumber & greaterThanOrEqual(18) & lowerThanOrEqual(100)',

    'orderLines'                => 'conventionalArray',
    'orderLines/*'              => 'associative',
    'orderLines/*/productId'    => 'uuid',
    'orderLines/*/count'        => 'integer & greaterThan(0)',
    'orderLines/*/comments'     => 'optional & string & shorterThan(1024)',
]);

As you can see, check for nested data via the / character.

You can get the error messages for a single field like so:

// get the errors associated with the top level field 'age'.
$errors = $checks->errorMessagesByPath('age');

// get the errors for the productId of the first orderLine.
$errors = $checks->errorMessagesByPath('orderLines/0/productId');

// get the error associated with the second orderLine
$errors = $checks->errorMessagesByPath('orderLines/1');

Utilities

Valit provides the Val facade that lets to do quick type juggling and assertions.

Below are ways of testing if a variable is iterable, that is agnostic of your php version.

use Valit\Util\Val;

if (!Val::is($container, 'iterable')) {
    throw new LogicException('$container should be iterable');
}

Or alternatively:

use Valit\Util\Val;

// an InvalidArgumentException will be thrown if $container is not iterable.
Val::mustBe($container, 'iterable');

Or with your own custom exception

use Valit\Util\Val;

$myException = throw LogicException('$container should be iterable');

// $myException will be thrown if $container is not iterable.
Val::mustBe($container, 'iterable', $myException);

Below are some of the type validations you can make.

$type Validation
null is_null()
object is_object()
int is_int()
integer is_int()
bool is_bool()
boolean is_bool()
string is_string()
float is_float()
double is_float()
numeric is_numeric()
intable stringable that can be converted to an int
nan is_nan()
inf is_inf()
callable is_callable()
iterable is_array() or is_a($value, 'Traversable')
countable is_array() or is_a($value, 'Cointable')
arrayable is_array() or is_a($value, 'ArrayAccess')
container iterable, countable and arrayable
stringable scalar or object with a__toString() method
class name is_a()
foo[] array of foo

Code examples:

// single type
Val::mustBe($value, 'callable');

// multiple allowed types via the pipe character
Val::mustBe($value, 'float | int');

// check that $foo is an array of floats
// or an array of integers
Val::mustBe($value, 'float[] | int[]');

// mixing classes, interfaces and basic types.
Val::mustBe($value, 'int|DateTime|DateTimeImmutable');

// multiple types via array notation
Val::mustBe($value, ['object', 'array']);

// a strict array with 0-based numeric index
Val::mustBe($value, 'mixed[]');

// a strict array of strict arrays
Val::mustBe($value, 'mixed[][]');