Docs LATEST

Response

The Response class represents HTTP responses with content, status codes, and headers.

HTTP

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 #

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