Skip to content

Building responses ​

A route handler decides what to return. The router accepts both plain values and HttpResponse instances, and the Responds trait provides short helpers for the common cases.

Returning plain values ​

A route method or closure may return any value. When the returned value is not already an HttpResponse, the router wraps it in a ResultHttpResponse automatically. This is the shortest way to answer a request with JSON-serializable data.

php
use Raxos\Router\Attribute\{Controller, Get};

#[Controller('/todos')]
final readonly class TodoController
{
    #[Get('/')]
    public function index(): array
    {
        return ['todos' => []];
    }
}

Returning a response directly ​

When you need control over the status code, headers or body type, return an HttpResponse instance. The router uses it as is. The Responds trait builds these for you.

php
<?php
declare(strict_types=1);

namespace App\Http\Controller;

use Raxos\Http\HttpResponseCode;
use Raxos\Router\Attribute\{Controller, Get, Post};
use Raxos\Router\Responds;

#[Controller('/todos')]
final readonly class TodoController
{
    use Responds;

    #[Get('/')]
    public function index(): mixed
    {
        return $this->json(['todos' => []]);
    }

    #[Post('/')]
    public function store(): mixed
    {
        return $this->json(['created' => true], responseCode: HttpResponseCode::CREATED);
    }
}

Available helpers ​

The Responds trait, used with use Responds;, adds a helper per common response type. Each returns an HttpResponse:

  • json: a JSON response.
  • html: an HTML response.
  • result: a generic result response, the same wrapper the router applies to plain return values.
  • redirect: a redirect response, defaulting to status 302 Found.
  • file: a file response for a path, honoring conditional request headers.
  • binary: a raw binary response.
  • noContent: a 204 No Content response.
  • notFound: a 404 Not Found response.
  • forbidden: a 403 Forbidden response.
  • error: a JSON error response for a JSON-serializable exception, using its responseCode when present.
php
use Raxos\Http\HttpRequest;

#[Get('/$id/download')]
public function download(HttpRequest $request, int $id): mixed
{
    return $this->file("/var/todos/{$id}.pdf", $request);
}

#[Get('/redirect')]
public function toIndex(): mixed
{
    return $this->redirect('/todos');
}

Validation errors ​

Two helpers build a standardized JSON validation error response. Use validationError for a single field and constraint, and validationErrors for several at once.

php
#[Post('/')]
public function store(HttpRequest $request): mixed
{
    if ($request->post->get('title') === null) {
        return $this->validationError('title', 'required', 'A title is required.');
    }

    return $this->json(['created' => true]);
}