Responses
All controller actions in a ZAPHYR application must return a PSR-7 response
object which implements the Psr\Http\Message\ResponseInterface
. This ensures that your application adheres to the
PSR-7 standard for HTTP messages, allowing for greater interoperability and flexibility in handling HTTP responses.
The framework provides several response types to handle different scenarios. You can use these response types to return HTML, JSON, text, redirects, or even empty responses. Each response type is designed to simplify the process of returning the appropriate HTTP response from your controller actions.
Basic Response
You can return a basic response using the Zaphyr\Framework\Http\Response
class. This class allows you to create a
response with a status code, headers, and a body. It is the most generic response type and can be used for any
purpose:
namespace App\Controllers;
use Zaphyr\Framework\Http\Response;
use Zaphyr\Router\Attributes\Get;
class BlogController
{
#[Get(path: '/blog/index', name: 'blog.index')]
public function indexAction(): Response
{
$response = new Response(headers: ['Content-Type' => 'text/html']);
$response->getBody()->write('<h1>Hello World!</h1>');
return $response;
}
}
return new Response(
body: 'php://memory',
status: 202,
headers: ['Content-Type' => 'text/plain']
);
Redirects
Sometimes, you may need to redirect a client to a different URL, for example, after a form submission or during
authentication. For this purpose, ZAPHYR provides the Zaphyr\Framework\Http\RedirectResponse
class.
This class extends the base Response
class and is specifically designed for handling HTTP redirects. It allows you to
set the target URL, the HTTP status code, and any additional headers, making it simple to perform both temporary and
permanent redirects.
Basic Redirect
To perform a standard redirect (default status: 302 Found
), pass the destination URL to the constructor:
return new RedirectResponse('/path/to/redirect');
The argument can be a relative path or an absolute URL. If you provide a relative path, it will be resolved based on the current request's base URL. This is particularly useful for redirecting within your application without hardcoding the full URL.
Custom Status and Headers
If needed, you can customize the status code, such as using 301 Moved Permanently
and add custom headers:
return new RedirectResponse('https://example.com', 301, ['X-Redirected' => 'true']);
Redirect Using Named Routes
In larger applications, it’s best practice to generate URLs dynamically using named routes. This approach avoids hardcoding URLs and ensures changes to routes don’t require updates across multiple controllers:
namespace App\Controllers;
use Zaphyr\Framework\Http\RedirectResponse;
use Zaphyr\Router\Attributes\Get;
use Zaphyr\Router\Contracts\RouterInterface;
class RedirectController
{
public function __construct(protected RouterInterface $router)
{
}
#[Get(path: '/redirect', name: 'redirect')]
public function redirectAction(): RedirectResponse
{
// Generates a URL from the named route 'welcome'
$url = $this->router->getPathFromName('welcome');
return new RedirectResponse($url);
}
}
Predefined Response Types
ZAPHYR provides a set of predefined response classes that extend the functionality of the base Response
class. These
specialized responses are designed to simplify common use cases such as returning HTML views, JSON or XML data, plain
text, or empty responses.
Each predefined response type implements the Psr\Http\Message\ResponseInterface
, ensuring full PSR-7 compliance.
Additionally, all of these response classes automatically set the appropriate Content-Type
header along with UTF-8
character encoding where applicable, reducing boilerplate and improving consistency.
HTML Response
Use the Zaphyr\Framework\Http\HtmlResponse
class to return HTML content. It automatically sets the Content-Type
header
to text/html; charset=utf-8
, making it suitable for rendering HTML documents or fragments:
return new HtmlResponse('<h1>Hello, World!</h1>');
This response type is commonly used to return HTML views rendered by a templating engine.
JSON Response
The Zaphyr\Framework\Http\JsonResponse
class is designed for returning JSON-encoded data, typically for APIs or AJAX
requests. It sets the Content-Type
header to application/json; charset=utf-8
and handles encoding the given array or
object into a JSON string:
return new JsonResponse(['message' => 'Hello, World!']);
This response class automatically serializes PHP arrays and objects implementing JsonSerializable
to JSON.
If the provided data cannot be encoded into a valid JSON string (e.g., due to circular references or invalid UTF-8
characters), the JsonResponse
class throws a Zaphyr\Framework\Http\Exceptions\ResponseException
. This ensures that
your application can fail gracefully and respond appropriately to encoding issues.
Example with a custom object implementing JsonSerializable
You can return a JSON response with a custom object by implementing the JsonSerializable
interface:
class MyJsonObject implements JsonSerializable
{
public function jsonSerialize(): mixed
{
return [
'message' => 'Hello, World!',
'status' => 'success',
];
}
}
return new JsonResponse(new MyJsonObject());
XML Response
To return XML-formatted data, use the Zaphyr\Framework\Http\XmlResponse
class. It sets the Content-Type
header to
application/xml; charset=utf-8
and converts the provided array or object into XML:
return new XmlResponse(['message' => 'Hello, World!']);
This is especially useful when working with services or clients that require XML rather than JSON.
Text Response
Use the Zaphyr\Framework\Http\TextResponse
class to return plain text. This response type sets the Content-Type
header to text/plain; charset=utf-8
, making it ideal for returning raw strings or log output:
Basic usage
You can pass a raw string directly to the constructor:
return new TextResponse('Hello, World!');
This is a straightforward and effective way to send plain text without any additional markup or formatting.
Using a Stream
Alternatively, you can pass a PSR-7 compatible stream if the text content is coming from an input stream or resource. This is useful for returning streamed or dynamically generated text content:
$stream = new Zaphyr\HttpMessage\Stream('php://input');
return new TextResponse($stream);
This method allows you to work with streamed data sources such as files, memory buffers, or PHP input streams, providing greater control over response output.
Empty Response
For cases where a response body is not needed—such as successful form submissions, background task triggers, or API
endpoints that return only a status—you can use the Zaphyr\Framework\Http\EmptyResponse
class:
return new EmptyResponse();
This response automatically sets the HTTP status code to 204 No Content
and omits the response body, conforming to the
semantics of RESTful APIs and reducing unnecessary response payloads.
Status Codes
ZAPHYR provides a convenient set of predefined HTTP status codes through the Zaphyr\Framework\Http\Utils\StatusCode
class. These constants allow you to clearly indicate the result of an HTTP request in a readable and standardized way.
Instead of using "magic numbers" like 200
, 404
, or 500
directly, you can reference meaningful named constants such
as StatusCode::OK
, StatusCode::NOT_FOUND
, or StatusCode::INTERNAL_SERVER_ERROR
.
Using Status Code Constants
To specify a status code in a response, use the appropriate constant:
$status = StatusCode::I_AM_A_TEAPOT; // 418
Get the Status Message
To retrieve the standard reason phrase for a status code (e.g., "OK", "Not Found", etc.), use the static getMessage()
method:
$message = StatusCode::getMessage(StatusCode::OK); // "OK"
All constants in the StatusCodes class map directly to their corresponding numeric HTTP status codes as defined in RFC 7231 and other relevant specifications.