Response
The response object based on PSR-7: Response.
A response is written as a class: what it carries is one method, and the status is where the class says it is. That way an endpoint's answer is a thing with a name rather than an array assembled somewhere in a controller.
Requirements
- PHP 8.1 or newer
Installation
composer require quillstack/responseUsage
A response of your own
Extend Response and say what it carries:
use Quillstack\Response\Response;
final class UserResponse extends Response
{
private string $id = '';
public function setId(string $id): self
{
$this->id = $id;
return $this;
}
public function send(): array
{
return ['id' => $this->id];
}
}$response = (new UserResponse())->setId('42');
$response->getStatusCode(); // 200
$response->getReasonPhrase(); // 'OK'
json_encode($response); // {"id":"42"}Saying what happened
The status comes from the constructor, so a response which means something other than success says so where it is defined rather than where it is used:
use Quillstack\HeaderBag\HeaderBag;
use Quillstack\Response\Response;
use Quillstack\Response\StatusCode;
final class NotFoundResponse extends Response
{
public function __construct(?HeaderBag $headerBag = null)
{
parent::__construct(StatusCode::NOT_FOUND, '', $headerBag ?? new HeaderBag());
}
public function send(): array
{
return ['error' => ['status' => $this->getStatusCode(), 'message' => $this->getReasonPhrase()]];
}
}The reason phrase is found from the code, so 404 is Not Found without anybody writing it down twice. Passing one explicitly overrides it.
Headers
Every change hands back a copy, so the response you were given stays as it was:
$response = (new UserResponse())
->withHeader('Content-Type', 'application/json')
->withAddedHeader('Set-Cookie', 'a=1');
$response->getHeaderLine('content-type'); // 'application/json'Building one from a factory
$factory->setResponseClass(UserResponse::class);
$response = $factory->createResponse(StatusCode::CREATED);Technical documentation
AbstractResponse implements Psr\Http\Message\ResponseInterface and JsonSerializable; Response is the class to extend, and send() is the one method to write.
| Method | Answers |
|---|---|
send(): array | what this response carries — the one thing you write |
getStatusCode(): int / withStatus($code, $reasonPhrase = '') | the status |
getReasonPhrase(): string | found from the code where none was given |
getHeaders(), getHeader(), getHeaderLine(), hasHeader() | headers, through quillstack/header-bag |
withHeader(), withAddedHeader(), withoutHeader() | a copy with them changed |
getBody() / withBody() | the body, as a PSR-7 stream |
getProtocolVersion() / withProtocolVersion() | the HTTP version |
StatusCode names every status this package knows — 44 of them, from CONTINUE (100) to HTTP_VERSION_NOT_SUPPORTED (505) — and StatusCode::REASON_PHRASES maps each to its phrase.
| Exception | Thrown when |
|---|---|
UnknownResponseCodeException | the status is not one of them |
UnableToFindReasonPhraseException | there is no phrase for that code |
UnknownResponseClassException | the factory is given a class which does not exist |
All extend ResponseException.
Unit tests
composer test
composer test:coverage
composer stanDocker
docker-compose up -d
docker exec -w /var/www/html -it quillstack_response shLicense
MIT. See LICENSE.