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:
<?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]);
}
}
Learn about Routing to connect URLs to your controllers, Requests for handling input, Responses for output, and Validation for input rules.