PHP MVCDOCUMENTAÇÃO
v2.0.0

Respostas HTTP e JSON

Como responder com HTML, redirect, status de erro e envelopes JSON sem inventar uma classe Response.

Precisão da API: não existe uma classe geral Framework\Http\Response neste projeto. A saída é realizada pelos helpers do Controller; para a API JSON existe Framework\Http\Api\ApiResponse.

HTML e redirecionamentos

view() imprime a view e o layout; redirect(), back() e redirectWith() enviam redirect e encerram. Helpers globais também incluem redirect($path). Alvos externos não confiáveis são rejeitados pelo helper de redirecionamento seguro.

JSON de controller Web

json($data,$status=200) envia JSON e finaliza. jsonSuccess() e jsonError() são conveniências; o formato deles não é idêntico ao envelope da ApiResponse.

Envelope da API própria

{
  "success": true,
  "message": "Dados encontrados.",
  "data": [],
  "meta": {"current_page": 1, "per_page": 15, "total": 0, "last_page": 0, "from": 1, "to": 0}
}

ApiResponse::success($data,$message,$status,$meta), paginated($result,$message) e error($message,$errors,$status) definem Content-Type, status HTTP e encerram via exit. Controllers API delegam a helpers em App\Http\Controllers\Api\ApiController.

Erros

Use abort($code,$message), abortIf() e abortUnless() nos controllers. O Router lida com rota inexistente, método não permitido e exceções em execução.

Controller Web · payload livre ou conveniência

Use `json()` quando o formato do payload já está definido pela aplicação. `jsonSuccess()` e `jsonError()` montam campos comuns, enviam Content-Type/status e encerram (retorno `never`). O terceiro parâmetro de jsonError é o status; dados adicionais entram no quarto campo como array.

$this->jsonSuccess('Perfil carregado.', ['data' => ['id' => 42]], 200);

// Erro terminal: mensagem + status + campos extras.
$this->jsonError('Registro não encontrado.', 404, ['code' => 'not_found']);

O payload de `jsonSuccess()` é `array_merge([success, message], $data)`: chaves repetidas em data podem sobrescrever os campos base. Prefira nomes sem colisão e documente o contrato. `json()` responde 500 se a serialização falhar.

API própria · envelope consistente

A API em /api/v1 usa `App\Http\Controllers\Api\ApiController` como base. `success($data,$message,$status,$meta)` retorna success/message/data e meta quando não vazio; `paginated($result,$message)` converte as chaves de Model::paginate() em meta; `error($message,$errors,$status)` omite errors quando vazio. Todos encerram a requisição.

// Dentro de um ApiController:
$this->success(['id' => 42, 'name' => 'Ana'], 'Usuário encontrado.');

// Erro validado: status semântico 422.
$this->error('Os dados enviados são inválidos.', $request->errors(), 422);
UsoStatus comumSaída
Sucesso genérico200 (ou explícito)success, message, data e meta opcional
Paginação200data é a lista; meta contém current_page/per_page/total/last_page/from/to
Validação API422success=false, message, errors por campo
Não encontrado404success=false, message e errors opcional
Falha de autenticação401Negada antes da action por middleware ou resposta de login
Não existe uma classe genérica Framework\Http\Response. `abort()` lança uma RuntimeException com código; o Router monta a resposta. Views/redirects são fluxo Web, enquanto ApiResponse é o envelope de /api/v1.

404, 405 e exceções durante o dispatch

O Router distingue rota inexistente (404) de caminho conhecido com método não permitido (405) e pode fornecer Allow na resposta de método. Isso não significa que qualquer exceção com código HTTP será mapeada ao status correspondente.

Limitação atual de abort(): dentro da action ou middleware despachada, Controller::abort(404) lança uma exceção, mas o handler de dispatch trata o Throwable como erro interno e fixa 500. O status contido na exceção é ignorado nesse caminho. Para status controlado em uma API, retorne explicitamente ApiResponse/jsonError(); não documente abort(404) como 404 até que o Router seja alterado.

O fallback 500 também pode revelar detalhes quando o Router lê $_ENV['APP_DEBUG'] diretamente; mantenha explicitamente APP_DEBUG=false em produção e consulte a página de configuração.