Constraints¶
Each Constraint
have the following methods:
->__invoke()
->and()
->or()
->map()
->asPredicate()
->__invoke()
¶
This method is the one to apply the validation on an input and will return a Validation
monad that will contain either the validated data or the error messages.
Let's take a simple example to check if the input of a method is a string
:
use Innmind\Validation\Is;
function(mixed $input): string {
$validate = Is::string();
return $validate($input)->match(
static fn(string $value) => $value,
static fn() => throw new \RuntimeException('Input is not a string');
);
}
Info
Note that we use the style $validate($input)
and not $validate->__invoke($input)
. This style allows to treat the constraints as if it were native functions.
->and()
¶
This method allows to apply extra validation on an input.
Let's take the example of making sure a string
is shorter than 255
characters:
use Innmind\Validation\{
Is,
Of,
Failure,
};
use Innmind\Immutable\Validation;
function(mixed $input): string {
$validate = Is::string()->and(Of::callable(
static fn(string $value) => match (true) {
\strlen($value) < 255 => Validation::success($value),
default => Validation::fail(Failure::of('String is too long')),
},
));
return $validate($input)->match(
static fn(string $value) => $value,
static fn() => throw new \RuntimeException('Input is not valid');
);
}
->or()
¶
This method allows to have an alternate validation in case the first one fails. This is useful for unions types.
Let's take the example where the input needs to be a string
or an int
:
use Innmind\Validation\Is;
function(mixed $input): string|int {
$validate = Is::string()->or(Is::int());
return return $validate($input)->match(
static fn(string|int $value) => $value,
static fn() => throw new \RuntimeException('Input is not valid');
);
}
->map()
¶
This method allows to transform the validated value to anything you want.
Let's take the example where a need a string
but want to output a Str
for ease of use afterwards:
use Innmind\Validation\Is;
use Innmind\Immutable\Str;
function(mixed $input): Str {
$validate = Is::string()->map(
static fn(string $value) => Str::of($value),
);
return return $validate($input)->match(
static fn(Str $value) => $value,
static fn() => throw new \RuntimeException('Input is not valid');
);
}
->asPredicate()
¶
A Predicate
acts as a function that returns a bool
.
It's intended to be used with Sequence::keep()
or Set::keep()
.
Here's an example to keep all string
s inside a Sequence
:
use Innmind\Validation\Is;
use Innmind\Immutable\Sequence;
Sequence::of(1, 'a', null, 'b', new \stdClass, 'c')
->keep(Is::string()->asPredicate())
->toList(); // returns ['a', 'b', 'c']
Note
There's no need to apply transformations on your constraints when used as predicates as the outputed value is not used.
Handling failures¶
In the examples above we've thrown exceptions in case of errors but you have access to all the failures messages and where they happened.
use Innmind\Validation\{
Is,
Failure,
};
use Innmind\Immutable\Sequence;
$validate = Is::shape('id', Is::int())
->with('username', Is::string());
$validate($input)->match(
static fn(array $valid) => $valid,
static fn(Sequence $failures) => \var_dump(
$failures
->map(static fn(Failure $failure) => [
$failure->path()->toString(),
$failure->message(),
])
->toList(),
),
);
In case $input
is invalid it will print: