Controllers & responses
Controllers keep route files focused. Elang resolves constructor dependencies and handler parameters from the service container.
An invokable controller
namespace App\Controllers;
use Elang\Http\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
final class HelloController
{
public function __invoke(): JsonResponse
{
return Response::json(['message' => 'Hello from Elang']);
}
}
Register it with $router->get('/hello', HelloController::class).
Read a request
use Symfony\Component\HttpFoundation\Request;
$router->get('/search', function (Request $request) {
return ['query' => $request->query->get('q', '')];
});
For JSON, decode $request->getContent() using JSON_THROW_ON_ERROR, verify the top-level structure, and validate fields. Form data is available through $request->request.
Response helpers
Response::json(['created' => true], 201);
Response::html('<h1>Hello</h1>');
Response::redirect('/dashboard');
The redirect helper accepts local absolute paths and rejects external or protocol-relative destinations. Returning raw HTML requires you to escape interpolated values; Twig templates handle escaping automatically.
Errors
Throw Elang\Http\HttpException with a status and safe public message. API errors use a JSON envelope with message and request_id. Internal errors are logged through PSR-3; stack traces are not sent to visitors.