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.