Controllers
Introduction
Controllers organize request handling logic into classes.
Creating Controllers
Extend the base Controller class:
php
<?php
namespace App\Controllers;
use Lighthouse\Controller;
use Psr\Http\Message\ResponseInterface;
class UserController extends Controller
{
public function index(): ResponseInterface
{
$users = [
['id' => 1, 'name' => 'John'],
['id' => 2, 'name' => 'Jane'],
];
return $this->view('users.index', ['users' => $users]);
}
public function show(string $id): ResponseInterface
{
return $this->json(['id' => $id, 'name' => 'John']);
}
}Registering Routes
Point routes to controller methods:
php
use App\Controllers\UserController;
$app->get('/users', [UserController::class, 'index']);
$app->get('/users/{id}', [UserController::class, 'show']);
$app->post('/users', [UserController::class, 'store']);Response Methods
The base controller provides convenient response methods:
View Response
php
public function index(): ResponseInterface
{
return $this->view('users.index', ['users' => $users]);
}JSON Response
php
public function show(string $id): ResponseInterface
{
return $this->json(['id' => $id, 'name' => 'John']);
}
// With status code
return $this->json(['error' => 'Not found'], 404);Redirect Response
php
public function store(): ResponseInterface
{
// Create user...
return $this->redirect('/users');
}
// Redirect to named route
return $this->redirectToRoute('users.show', ['id' => $user->id]);Text Response
php
return $this->text('Plain text content');HTML Response
php
return $this->html('<h1>Hello</h1>');Empty Response
php
return $this->empty(204); // No ContentDependency Injection
Controllers are resolved through the container. Type-hint dependencies:
php
<?php
namespace App\Controllers;
use Lighthouse\Application;
use Lighthouse\Controller;
use App\Services\UserService;
class UserController extends Controller
{
public function __construct(
Application $app,
private UserService $users
) {
parent::__construct($app);
}
public function index(): ResponseInterface
{
$users = $this->users->all();
return $this->view('users.index', ['users' => $users]);
}
}Accessing the Request
Inject ServerRequestInterface into methods:
php
use Psr\Http\Message\ServerRequestInterface;
public function store(ServerRequestInterface $request): ResponseInterface
{
$data = $request->getParsedBody();
// Create user with $data['name'], $data['email'], etc.
return $this->redirect('/users');
}Route Parameters
Route parameters are injected by name:
php
// Route: /users/{id}/posts/{postId}
public function show(string $id, string $postId): ResponseInterface
{
return $this->json([
'user_id' => $id,
'post_id' => $postId,
]);
}Invokable Controllers
For single-action controllers, use __invoke:
php
<?php
namespace App\Controllers;
use Lighthouse\Controller;
use Psr\Http\Message\ResponseInterface;
class ShowDashboardController extends Controller
{
public function __invoke(): ResponseInterface
{
return $this->view('dashboard');
}
}Register without a method:
php
$app->get('/dashboard', ShowDashboardController::class);