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:
| Rule | Meaning |
|---|---|
required / nullable / sometimes | Presence handling. |
string / int / numeric / bool / array | Type checks (int and bool are cast on success). |
email / url / alpha / alnum | Format checks. |
min / max / between | Size or range, e.g. min:18, between:1,100. |
in | One of a fixed set, e.g. in:admin,user. |
same / confirmed | Field matching (great for password confirmation). |
regex | Match 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.