Repository navigation
JsonResponse
Pair\Http\JsonResponse is the explicit JSON response object for Pair v4 controllers.
Use it when an action should return a ResponseInterface instead of sending JSON immediately through legacy helpers.
Arguments:
-
payload: JSON payload to emit. Arrays, objects, read models, scalar values, andnullare accepted. -
httpCode: HTTP status code. -
headers: optional additional headers keyed by header name.
Example:
use Pair\Http\JsonResponse;
return new JsonResponse(['saved' => true], 201);With explicit cache headers:
return new JsonResponse(['id' => 7], 200, [
'ETag' => '"abc123"',
'Cache-Control' => 'public, max-age=300',
]);Read-model payloads are converted to arrays before JSON encoding.
Read-model example (the version belongs to the application):
use Pair\Data\ArraySerializableData;
use Pair\Data\ReadModel;
use Pair\Http\JsonResponse;
/**
* Public health payload for an API endpoint.
*/
final readonly class HealthReadModel implements ReadModel {
use ArraySerializableData;
/**
* Build the health payload.
*/
public function __construct(
public bool $ok,
public string $version
) {}
/**
* Export the public health payload.
*
* @return array<string, mixed>
*/
public function toArray(): array {
return [
'ok' => $this->ok,
'version' => $this->version,
];
}
}
return new JsonResponse(new HealthReadModel(true, '1.0.0'), 200);-
send()emitsContent-Type: application/jsonand then any additional headers. Passing aContent-Typeheader replaces the default, which is how Problem Details responses useapplication/problem+json. - PHP-empty payloads keep the historical promotion to HTTP
204, overriding the requested status. This includesnull,false,0,0.0,'','0', and[]after top-level read-model normalization. - The legacy promotion changes the status but still calls JSON encoding and prints the encoded value. For an explicit response with no body, return
EmptyResponse. If an empty collection must retain HTTP200, put it inside a non-empty envelope such as['data' => []]. -
send()does not terminate execution by itself; the v4 dispatcher sends the response and then finishes the request. - When
APP_DEBUG=trueand observability debug headers are enabled,send()also emits Pair correlation and trace timing headers. - Legacy
ApiResponse::respond(),error(),success(), andpaginated()still terminate after sending to preserve their old contract.
For Pair v4 web controllers, prefer the helper methods on Pair\Web\Controller when the endpoint should follow the shared JSON conventions:
return $this->dataResponse([
'updatedRows' => 12,
], 'Operation completed.');This emits successful responses with domain data under data and non-domain metadata under meta:
{
"data": {
"updatedRows": 12
},
"meta": {
"message": "Operation completed."
}
}For HTTP errors, use Problem Details:
return $this->problemResponse(
'urn:pair:problem:invalid-request',
'Invalid request',
422,
'The submitted request is missing a required field.',
'INVALID_REQUEST'
);This returns application/problem+json with the RFC 9457 base members plus optional Pair extension members such as code or errors.
Scalar payloads are supported for bridge cases such as idempotency replay:
return new JsonResponse('stored', 200);Normal public API endpoints should still prefer explicit array/object/read-model payloads.
See also: API, ApiResponse, ApiErrorResponse, ReadModel, ResponseInterface, HttpCache, Observability, EmptyResponse, TextResponse.
Maintained by Viames Marino — VM Ingegneria · Professional enquiries
Home · Setup · Configuration
Build with Pair 4
- Generator
- Controllers and responses
- Read models
- ActiveRecord and queries
- Forms and validation
- PairUI.js and HTML fragments
APIs and authentication
- API guide and CRUD
- Middleware and rate limits
- Users, sessions, and ACL
- Passkeys and social login
- Native mobile setup
Integrate and operate
- Integrations
- Runtime extensions and adapter keys
- Cache and cache stores
- Logs and observability
- PWA and push
- Packages and distribution
- Upgrade to v4