Response
The Response class represents HTTP responses with content, status codes, and headers.
Namespace: VelvetCMS\Http\Response
Definition #
class Response
{
public function __construct(
string $content = '',
int $status = 200,
array $headers = []
);
// Static factories
public static function html(string $content, int $status = 200): self;
public static function json(array|object $data, int $status = 200): self;
public static function redirect(string $url, int $status = 302): self;
public static function notFound(string $message = 'Not Found'): self;
public static function error(string $message, int $status = 500): self;
public static function methodNotAllowed(array $allowed): self;
public static function file(string $path, ?string $mimeType = null, array $headers = [], int $status = 200): self;
// Fluent modifiers
public function header(string $name, string $value): self;
public function headers(array $headers): self;
public function status(int $status): self;
// Output
public function send(): void;
// Accessors
public function getContent(): string;
public function getStatus(): int;
public function getHeaders(): array;
public function getHeader(string $name): ?string;
}
Static Factories #
html() #
Create an HTML response.
public static function html(string $content, int $status = 200): self
| Parameter | Type | Description |
|---|---|---|
$content |
string |
HTML content |
$status |
int |
HTTP status code |
Example:
return Response::html('<h1>Hello World</h1>');
return Response::html(view('pages.show', ['page' => $page]));
return Response::html('<h1>Forbidden</h1>', 403);
json() #
Create a JSON response.
public static function json(array|object $data, int $status = 200): self
| Parameter | Type | Description |
|---|---|---|
$data |
array|object |
Data to encode |
$status |
int |
HTTP status code |
Example:
return Response::json(['message' => 'Success']);
return Response::json([
'data' => $users,
'meta' => ['total' => count($users)]
]);
return Response::json(['error' => 'Invalid input'], 422);
redirect() #
Create a redirect response.
public static function redirect(string $url, int $status = 302): self
| Parameter | Type | Description |
|---|---|---|
$url |
string |
Target URL |
$status |
int |
302 (temporary) or 301 (permanent) |
Example:
// Temporary redirect
return Response::redirect('/dashboard');
// Permanent redirect
return Response::redirect('/new-url', 301);
// External redirect
return Response::redirect('https://example.com');
// Using helper
return redirect('/login');
notFound() #
Create a 404 Not Found response.
public static function notFound(string $message = 'Not Found'): self
Example:
return Response::notFound();
return Response::notFound('Page not found');
error() #
Create an error response.
public static function error(string $message, int $status = 500): self
Example:
return Response::error('Internal Server Error');
return Response::error('Service Unavailable', 503);
methodNotAllowed() #
Create a 405 Method Not Allowed response.
public static function methodNotAllowed(array $allowed): self
| Parameter | Type | Description |
|---|---|---|
$allowed |
array |
List of allowed methods |
Automatically sets the Allow header.
Example:
return Response::methodNotAllowed(['GET', 'POST']);
// Sets header: Allow: GET, POST
file() #
Create a file download response.
public static function file(
string $path,
?string $mimeType = null,
array $headers = [],
int $status = 200
): self
| Parameter | Type | Description |
|---|---|---|
$path |
string |
Absolute file path |
$mimeType |
string|null |
MIME type (auto-detected if null) |
$headers |
array |
Additional headers |
$status |
int |
HTTP status code |
Throws: InvalidArgumentException if file not readable.
Example:
// Auto-detect MIME type
return Response::file(storage_path('documents/report.pdf'));
// Force download
return Response::file(
storage_path('exports/data.csv'),
'text/csv',
['Content-Disposition' => 'attachment; filename="export.csv"']
);
// Serve image
return Response::file(
storage_path('uploads/avatar.jpg'),
'image/jpeg'
);
Fluent Modifiers #
header() #
Add a single header.
public function header(string $name, string $value): self
Example:
return Response::html($content)
->header('X-Custom', 'value')
->header('Cache-Control', 'no-cache');
headers() #
Add multiple headers.
public function headers(array $headers): self
Example:
return Response::json($data)->headers([
'X-Total-Count' => $total,
'X-Page' => $page,
'Access-Control-Allow-Origin' => '*',
]);
status() #
Set the HTTP status code.
public function status(int $status): self
Example:
return Response::html($content)->status(201);
Output #
send() #
Send the response to the client.
public function send(): void
Outputs status code, headers, and content. Called automatically by the framework at the end of request handling.
Accessors #
getContent() #
Get the response body.
public function getContent(): string
getStatus() #
Get the HTTP status code.
public function getStatus(): int
getHeaders() #
Get all headers.
public function getHeaders(): array
getHeader() #
Get a specific header (case-insensitive).
public function getHeader(string $name): ?string
Example:
$contentType = $response->getHeader('Content-Type');
// "application/json; charset=utf-8"
Usage Examples #
Controller Responses #
class PostController
{
public function index(): Response
{
$posts = $this->postService->all();
return Response::html(view('posts.index', ['posts' => $posts]));
}
public function show(Request $request, string $slug): Response
{
$post = $this->postService->find($slug);
if (!$post) {
return Response::notFound('Post not found');
}
return Response::html(view('posts.show', ['post' => $post]));
}
public function store(Request $request): Response
{
$data = $request->validate([
'title' => 'required|max:200',
'content' => 'required',
]);
$post = $this->postService->create($data);
return Response::redirect("/posts/{$post->slug}");
}
}
API Responses #
class ApiController
{
public function list(Request $request): Response
{
$page = (int) $request->query('page', 1);
$limit = min((int) $request->query('limit', 20), 100);
$result = $this->service->paginate($page, $limit);
return Response::json([
'data' => $result->items,
'meta' => [
'page' => $page,
'limit' => $limit,
'total' => $result->total,
]
])->headers([
'X-Total-Count' => $result->total,
]);
}
public function create(Request $request): Response
{
try {
$data = $request->validate([
'name' => 'required|max:100',
'email' => 'required|email',
]);
$item = $this->service->create($data);
return Response::json([
'data' => $item,
'message' => 'Created successfully'
], 201);
} catch (ValidationException $e) {
return Response::json([
'errors' => $e->errors()
], 422);
}
}
}
File Downloads #
public function download(Request $request, string $id): Response
{
$document = $this->documentService->find($id);
if (!$document) {
return Response::notFound();
}
$path = storage_path("documents/{$document->filename}");
return Response::file($path, null, [
'Content-Disposition' => "attachment; filename=\"{$document->original_name}\"",
]);
}
Conditional Responses #
public function show(Request $request, string $id): Response
{
$item = $this->service->find($id);
if (!$item) {
if ($request->expectsJson()) {
return Response::json(['error' => 'Not found'], 404);
}
return Response::notFound('Item not found');
}
if ($request->expectsJson()) {
return Response::json(['data' => $item]);
}
return Response::html(view('items.show', ['item' => $item]));
}
Common Status Codes #
| Code | Constant/Method | Description |
|---|---|---|
| 200 | (default) | OK |
| 201 | .status(201) |
Created |
| 204 | .status(204) |
No Content |
| 301 | redirect($url, 301) |
Moved Permanently |
| 302 | redirect($url) |
Found (Temporary) |
| 400 | .status(400) |
Bad Request |
| 401 | .status(401) |
Unauthorized |
| 403 | .status(403) |
Forbidden |
| 404 | notFound() |
Not Found |
| 405 | methodNotAllowed() |
Method Not Allowed |
| 422 | .status(422) |
Unprocessable Entity |
| 500 | error() |
Internal Server Error |
| 503 | error($msg, 503) |
Service Unavailable |