Validation

Never trust input from the outside world. Fast's validate() helper checks incoming data against a set of rules and hands you back a clean, lightly cast subset, or throws an exception that the kernel turns into a proper 422 response. It is pure, meaning it has no dependencies and no side effects, so you can use it anywhere.

The basics

Pass the data and a map of field-to-rules. What comes back is only the validated fields, with a few types cast for you:

$data = validate(request()->form(), [
	'email' => 'required|email',
	'age'   => 'nullable|int|min:18',
	'role'  => 'required|in:admin,user',
]);

If everything passes, $data holds the clean values. Note that age comes back as a real int when present, not a string, because the int rule casts on success. If anything fails, validate() throws a ValidationException, and the kernel renders it as JSON or text depending on the request's Accept header, with a 422 status. You do not have to catch it for the common case.

Available rules

Rules are pipe-separated, and you can stack as many as you need on a field:

RuleMeaning
required / nullable / sometimesPresence handling.
string / int / numeric / bool / arrayType checks (int and bool are cast on success).
email / url / alpha / alnumFormat checks.
min / max / betweenSize or range, e.g. min:18, between:1,100.
inOne of a fixed set, e.g. in:admin,user.
same / confirmedField matching (great for password confirmation).
regexMatch a pattern.

required and nullable are position-independent, so their order among the other rules does not matter. The int and bool rules use filter_var under the hood, which means non-canonical input (like "12abc" for an int) fails rather than being silently truncated.

Patterns with special characters

Because rules are pipe-separated, a regex pattern that itself contains |, ,, or : would confuse the string parser. For those, use the array form of a rule, where each rule is its own array element:

$data = validate(request()->form(), [
	'slug' => ['required', ['regex', '/^[a-z0-9]+$/']],
]);

The array form is the escape hatch whenever a rule's argument contains a character that the pipe syntax uses as a separator.

Confirmation fields

The confirmed rule is a small convenience for the classic "type your password twice" pattern. A field password with the confirmed rule expects a matching password_confirmation field:

$data = validate(request()->form(), [
	'password' => 'required|string|min:8|confirmed',
]);

Throwing your own errors

validate() throws an HttpException under the hood, and you can throw one yourself from anywhere to short-circuit with a specific status and an optional structured payload:

use Fast\Http\HttpException;

throw new HttpException(403, 'Not allowed', ['reason' => 'insufficient role']);

The kernel renders it the same way it renders validation failures, respecting the request's Accept header. That gives you consistent error responses across your whole app without a bunch of manual response building.

Next we look at how Fast wires services together with the Container & Services.