Validation
ZephyrPHP provides a simple, expressive validation system to ensure your data meets your requirements.
Basic Validation
Validate incoming request data in your controllers:
<?php
class UserController extends Controller
{
public function store()
{
$data = $this->validate([
'name' => 'required|min:3|max:255',
'email' => 'required|email',
'password' => 'required|min:8',
]);
// If validation fails, user is redirected back with errors
// If it passes, $data contains the validated input
$user = new User();
$user->fill($data)->save();
return $this->redirect('/users');
}
}
Available Rules
| Rule | Description |
|---|---|
required |
Field must be present and not empty |
email |
Must be a valid email address |
numeric |
Must be numeric |
integer |
Must be an integer |
min:value |
Minimum string length or numeric value |
max:value |
Maximum string length or numeric value |
between:min,max |
Value must be between min and max |
url |
Must be a valid URL |
alpha |
Only alphabetic characters |
alpha_num |
Only alphanumeric characters |
in:val1,val2,... |
Value must be one of the listed values |
not_in:val1,val2,... |
Value must not be one of the listed values |
confirmed |
Field must have a matching field_confirmation |
date |
Must be a valid date |
regex:pattern |
Must match the regular expression |
Multiple Rules
Combine multiple rules with the pipe character:
$data = $this->validate([
'username' => 'required|alpha_num|min:3|max:20',
'age' => 'required|integer|min:18|max:120',
'website' => 'url',
'role' => 'required|in:user,admin,editor',
]);
Custom Error Messages
Provide custom error messages for validation rules:
$data = $this->validate([
'email' => 'required|email',
'password' => 'required|min:8',
], [
'email.required' => 'We need your email address.',
'email.email' => 'Please enter a valid email.',
'password.required' => 'A password is required.',
'password.min' => 'Password must be at least 8 characters.',
]);
Displaying Errors
Show validation errors in your Twig templates:
{# Display all errors #}
{% if errors %}
<div class="alert alert-danger">
<ul>
{% for field, messages in errors %}
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
{% endfor %}
</ul>
</div>
{% endif %}
{# Display error for specific field #}
<input type="email" name="email" value="{{ old('email') }}"
class="{{ errors.email ? 'is-invalid' : '' }}">
{% if errors.email %}
<span class="error">{{ errors.email|first }}</span>
{% endif %}
Old Input
Preserve user input after validation fails:
<form method="POST" action="/register">
{{ csrf_field()|raw }}
<input type="text" name="name" value="{{ old('name') }}">
<input type="email" name="email" value="{{ old('email') }}">
<button type="submit">Register</button>
</form>
Manual Validation
For more control, validate manually:
public function store()
{
$errors = [];
$input = $this->request->all();
if (empty($input['name'])) {
$errors['name'][] = 'Name is required';
} elseif (strlen($input['name']) < 3) {
$errors['name'][] = 'Name must be at least 3 characters';
}
if (empty($input['email'])) {
$errors['email'][] = 'Email is required';
} elseif (!filter_var($input['email'], FILTER_VALIDATE_EMAIL)) {
$errors['email'][] = 'Please enter a valid email';
}
if (!empty($errors)) {
return $this->backWithErrors($errors);
}
// Validation passed, continue...
}
Password Confirmation
Validate password confirmation:
$data = $this->validate([
'password' => 'required|min:8|confirmed',
]);
// This expects a 'password_confirmation' field in the form
<form method="POST">
{{ csrf_field()|raw }}
<input type="password" name="password">
<input type="password" name="password_confirmation">
<button type="submit">Submit</button>
</form>
Conditional Validation
Apply rules conditionally:
public function store()
{
$rules = [
'name' => 'required|min:3',
'email' => 'required|email',
];
// Add password rules only for new users
if (!$this->request->has('id')) {
$rules['password'] = 'required|min:8';
}
$data = $this->validate($rules);
// ...
}
API Validation
For API endpoints, return JSON validation errors:
use ZephyrPHP\Core\Http\Response;
public function apiStore()
{
$errors = [];
if (empty($this->request->input('email'))) {
$errors['email'][] = 'Email is required';
}
if (!empty($errors)) {
return Response::validationError($errors);
}
// Continue processing...
}
This returns a 422 response with JSON:
{
"message": "Validation failed",
"errors": {
"email": ["Email is required"]
}
}
Best Practice
Always validate user input, even if you're also validating on the client side. Server-side validation is your last line of defense against malicious input.