Controllers

Controllers handle incoming HTTP requests and return responses. They organize your application's logic into reusable classes.

Creating Controllers

Create a controller using the Craftsman CLI:

php craftsman make:controller UserController

This creates app/Controllers/UserController.php:

app/Controllers/UserController.php
<?php

namespace App\Controllers;

use ZephyrPHP\Core\Controllers\Controller;

class UserController extends Controller
{
    public function index()
    {
        return $this->render('users/index');
    }
}

Basic Controller

All controllers extend the base Controller class, which provides helpful methods for rendering views, redirects, and more.

<?php

namespace App\Controllers;

use ZephyrPHP\Core\Controllers\Controller;
use App\Models\User;

class UserController extends Controller
{
    public function index()
    {
        $users = User::query()->all();

        return $this->render('users/index', [
            'users' => $users
        ]);
    }

    public function show(int $id)
    {
        $user = User::find($id);

        if (!$user) {
            abort(404, 'User not found');
        }

        return $this->render('users/show', ['user' => $user]);
    }
}

Request Handling

Access request data through the $this->request property:

public function store()
{
    // Get all input data
    $data = $this->request->all();

    // Get specific input
    $name = $this->request->input('name');
    $email = $this->request->input('email', 'default@example.com');

    // Check if input exists
    if ($this->request->has('remember')) {
        // ...
    }

    // Get only specific fields
    $credentials = $this->request->only(['email', 'password']);

    // Exclude specific fields
    $data = $this->request->except(['_token', '_method']);
}

Request Methods

// Check HTTP method
if ($this->request->isPost()) { }
if ($this->request->isPut()) { }
if ($this->request->isDelete()) { }
if ($this->request->isAjax()) { }

// Get the HTTP method
$method = $this->request->method();

// Get the request path
$path = $this->request->path();

// Get the full URL
$url = $this->request->url();

Rendering Views

Return Twig templates using the render() method:

public function index()
{
    return $this->render('users/index', [
        'title' => 'All Users',
        'users' => User::query()->all(),
        'stats' => [
            'total' => User::query()->count(),
            'active' => User::query()->where('active', '=', true)->count()
        ]
    ]);
}

Redirects

Redirect users to different URLs:

// Simple redirect
return $this->redirect('/users');

// Redirect with status code
return $this->redirect('/login', 301);

// Redirect to named route
return $this->redirectToRoute('users.show', ['id' => $user->id]);

// Redirect back to previous page
return $this->back();

// Redirect back with fallback
return $this->back('/dashboard');

Flash Messages

Display one-time messages after redirects:

public function store()
{
    // Create the user...

    $this->flash('success', 'User created successfully!');
    return $this->redirect('/users');
}

public function destroy(int $id)
{
    // Delete the user...

    $this->flash('error', 'User has been deleted.');
    return $this->redirect('/users');
}

Access flash messages in your Twig templates:

{% if session('flash_success') %}
    <div class="alert alert-success">
        {{ session('flash_success') }}
    </div>
{% endif %}

{% if session('flash_error') %}
    <div class="alert alert-danger">
        {{ session('flash_error') }}
    </div>
{% endif %}

Validation

Validate incoming request data:

public function store()
{
    $data = $this->validate([
        'name' => 'required|min:3|max:255',
        'email' => 'required|email',
        'password' => 'required|min:8',
        'age' => 'numeric|min:18'
    ]);

    // 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');
}

Custom Error Messages

$data = $this->validate([
    'email' => 'required|email',
], [
    'email.required' => 'We need your email address.',
    'email.email' => 'Please provide a valid email.',
]);

Manual Validation

public function store()
{
    $errors = [];

    if (empty($this->request->input('name'))) {
        $errors['name'] = 'Name is required';
    }

    if (!empty($errors)) {
        return $this->backWithErrors($errors);
    }

    // Continue processing...
}

JSON Responses

Return JSON for API endpoints:

use ZephyrPHP\Core\Http\Response;

public function apiIndex()
{
    $users = User::query()->all();

    return Response::json([
        'data' => $users,
        'count' => count($users)
    ]);
}

public function apiStore()
{
    $user = new User();
    $user->fill($this->request->all())->save();

    return Response::created($user);
}

public function apiError()
{
    return Response::validationError([
        'email' => ['The email has already been taken.']
    ]);
}

Session Access

Work with session data in your controllers:

// Get session value
$userId = $this->session->get('user_id');

// Set session value
$this->session->set('last_activity', time());

// Check if session key exists
if ($this->session->has('user_id')) {
    // ...
}

// Remove session key
$this->session->remove('temporary_data');

// Get CSRF token
$token = $this->session->csrf();

Constructor Injection

Inject dependencies through the constructor:

<?php

namespace App\Controllers;

use ZephyrPHP\Core\Controllers\Controller;
use App\Services\UserService;

class UserController extends Controller
{
    private UserService $userService;

    public function __construct(UserService $userService)
    {
        parent::__construct();
        $this->userService = $userService;
    }

    public function index()
    {
        $users = $this->userService->getAllActive();
        return $this->render('users/index', ['users' => $users]);
    }
}
Related

Learn about Routing to connect URLs to your controllers, Requests for handling input, Responses for output, and Validation for input rules.