Controllers
Responsabilidades do controller base e utilitários reais de resposta.
Classe base
Controllers Web da aplicação herdam de Framework\Http\Controller (no projeto, via App\Http\Controllers\Web\BaseController). O Router instancia a classe e chama a action pública após executar middleware; a classe base cria Request em $this->request. O exemplo seguinte é um método real de AuthController, sem depender de um repositório ilustrativo.
class AuthController extends BaseController
{
public function login(): void
{
$request = new LoginRequest();
$data = $this->validateRequest($request, 'auth/login', ['email']);
$remember = isset($_POST['remember']) && $_POST['remember'] === '1';
$result = $this->authService->login($data['email'], $data['password'], $remember);
if (!$result['success']) {
Session::flash('error', $result['message']);
Session::flashInput(['email' => $data['email']]);
$this->redirect('auth/login');
}
$this->redirect('dashboard');
}
}
Métodos disponíveis aos filhos
view($view, $data = [], $layout = null);viewOnly($view, $data = []).redirect($url),back(),redirectWith($url,$type,$message).json($data,$status=200),jsonSuccess($message='OK',$data=[],$status=200),jsonError($message,$status=400,$data=[]).flash($type,$message); helpers de autenticaçãoauth(),user(),userId(),userRole().checkMethod(),validate(),validateRequest(),abort(),abortIf(),abortUnless().
FormRequest e autorização
O Router identifica parâmetros de action tipados com um FormRequest e repassa os parâmetros nomeados da rota ao instanciá-lo. Consulte Requests e FormRequest.
Papel do Controller no MVC
O Router instancia a classe e chama uma action pública após identificar a rota e concluir os middlewares. O Controller recebe um Request no construtor base; ele interpreta a entrada, coordena as próximas camadas e escolhe a resposta. Não é o local para concentrar SQL, regras reutilizáveis ou templates.
Request HTTP
→ Router encontra método/caminho
→ Middleware autoriza ou interrompe
→ Controller action
→ Service / Repository / Model
→ View ou JSON / redirect
→ resposta HTTPAs rotas reais de autenticação estão em routes/web.php. Para ver o ponto de entrada e a ordem de despacho, consulte Ciclo da requisição e Roteamento.
Básico · renderizar ou redirecionar
Cenário: visitante abre a raiz do site. A implementação real verifica a autenticação e escolhe entre encaminhar ao dashboard ou renderizar a página pública. A action retorna void porque os helpers emitem a saída.
class HomeController extends BaseController
{
public function index(): void
{
$this->auth()
? $this->redirect('dashboard')
: $this->view('home.index', ['title' => 'Início'], 'home');
}
}O `auth()` é um helper protegido que consulta o estado web. `view()` recebe o nome por dot notation, os dados e o layout; `redirect()` é terminal. Esta é a action real de App\Http\Controllers\Web\HomeController.
Intermediário · validar, delegar e redirecionar (trecho real)
Cenário: POST /auth/login. O grupo /auth e o middleware CSRF/rate-limit já protegem a rota. O FormRequest aplica regras e normalização; `validateRequest()` guarda somente os campos seguros pedidos se houver erro e interrompe por redirect. O Service tenta autenticar; o Controller traduz o resultado para flash + navegação.
class AuthController extends BaseController
{
public function login(): void
{
$request = new LoginRequest();
$data = $this->validateRequest($request, 'auth/login', ['email']);
$remember = isset($_POST['remember']) && $_POST['remember'] === '1';
$result = $this->authService->login($data['email'], $data['password'], $remember);
if (!$result['success']) {
Session::flash('error', $result['message']);
Session::flashInput(['email' => $data['email']]);
$this->redirect('auth/login');
}
$this->redirect('dashboard');
}
}Esse recorte corresponde a App\Http\Controllers\Web\AuthController::login(). A senha não é repassada como old input. O resultado do Service é um array de domínio, não uma resposta HTTP; escolher redirect/JSON é responsabilidade do Controller.
Completo · action de API já registrada
Em GET /api/v1/users/{id}, ApiAuthMiddleware autentica o token antes da action. A implementação real consulta UserRepository, converte o objeto em UserResource e responde pelo envelope padronizado da API.
class UserApiController extends ApiController
{
public function show(int $id): void
{
$user = $this->users->findById($id);
if (!$user) {
$this->error('Usuário não encontrado.', [], 404);
}
$this->success(UserResource::make($user));
}
}O `int $id` vem do placeholder nomeado `{id}`. `error()` e `success()` encerram o fluxo, por isso a execução não continua após eles. Veja contratos de resposta e rotas da API.
Consulte a referência detalhada, com assinatura, parâmetros, retorno, efeitos e exemplos, em Métodos herdados do Controller. Para campos HTTP, use $this->request e a página de Requests.
Métodos herdados do Controller: referência prática
As assinaturas abaixo são métodos de instância protegidos, disponíveis em subclasses. view* emite HTML; redirects e helpers JSON encerram o fluxo; validação Web pode redirecionar. Para endpoints JSON, prefira os contratos de API e respostas HTTP.
Renderização e navegação
view(string $view, array $data = [], string|false|null $layout = null): void
Resolve e renderiza a view com as variáveis de $data. false ou string vazia desliga o layout; null usa $this->defaultLayout (por padrão, string vazia/sem layout; a subclasse pode sobrescrever a propriedade e a aplicação pode definir DEFAULT_LAYOUT). Tokens CSRF compatíveis são injetados no HTML. Use para resposta HTML de uma action.
$this->view('users.show', ['user' => $user], 'main');A view precisa existir sob resources/views; valores interpolados continuam exigindo escaping contextual.
viewOnly(string $view, array $data = []): void
Atalho para renderizar sem layout. Retorno void; a saída vai diretamente ao corpo HTTP.
$this->viewOnly('emails.preview', ['message' => $message]);redirect(string $url): never e back(): never
redirect() envia um destino local seguro ou permitido e termina a requisição; back() usa o Referer validado e cai no destino padrão se ele for ausente/inseguro. Caminhos relativos sem barra inicial, como dashboard, não são aceitos como rota e podem cair em APP_URL; use /dashboard quando a intenção for esse caminho.
$this->redirect('/dashboard');
$this->back();Use depois de uma operação Web; não é um mecanismo de resposta JSON.
redirectWith(string $url, string $type, string $message): never
Grava a mensagem na sessão pela chave $type e redireciona. Os argumentos são destino, chave (por exemplo, success/error) e texto.
$this->redirectWith('/users', 'success', 'Usuário criado.');A view seguinte deve consumir o flash; não grave segredos ou tokens na mensagem.
Respostas JSON
json(mixed $data, int $status = 200): never
Define tipo JSON, serializa o payload e encerra. A codificação inválida resulta em erro 500.
$this->json(['id' => $id], 201);jsonSuccess(string $message = 'OK', array $data = [], int $status = 200): never
Emite success=true, message e os campos de $data. Como usa array_merge, chaves coincidentes em $data podem substituir os valores padrão; evite colisões.
$this->jsonSuccess('Criado', ['user' => $user], 201);jsonError(string $message, int $status = 400, array $data = []): never
Emite success=false, mensagem e campos extras com o status HTTP fornecido.
$this->jsonError('Entrada inválida', 422, ['errors' => $errors]);Não troque a ordem: o segundo argumento é o status, o terceiro é o array extra.
Sessão, identidade e método
flash(string $type, string $message): void
Armazena uma mensagem de sessão para leitura posterior. O getter de flash remove a chave quando lida; mensagens nunca consumidas não devem ser tratadas como expiração automática.
$this->flash('success', 'Alterações salvas.');auth(): bool, user(): ?object, userId(): int, userRole(): string
Consultam a identidade de sessão atual: autenticação, usuário carregado e identificadores/role. userId() usa zero quando não há usuário; userRole() usa o fallback da implementação. São getters, não guards: proteja rotas com middleware/guards e verifique auth() antes de confiar nos dados.
if (!$this->auth()) {
$this->redirect('/auth/login');
}
$userId = $this->userId();checkMethod(string|array $types, string $message = 'Requisição inválida.', int $status = 400): void
Continua quando o método/tipo solicitado corresponde ao da requisição; aceita os tipos implementados ajax, json, get, post, put, patch e delete. Caso contrário, responde em JSON com a mensagem/status informados. Um tipo desconhecido lança InvalidArgumentException e pode virar 500 no dispatch.
$this->checkMethod('post', 'Envie um formulário POST.', 405);Validação Web e encerramento por erro
validate(array $data, array $rules, string $redirectBack = ''): array
Valida os dados e devolve o próprio array de entrada se válido; não filtra para apenas campos validados. Em falha, grava erros e todo o input como old input e redireciona. Não passe senhas, tokens ou arquivos se não quiser persistir esses valores na sessão; prefira FormRequest com allowlist de campos a repassar.
$data = $this->validate($this->request->all(), [
'email' => 'required|email',
], '/users/create');validateRequest(object $request, string $redirectBack = '', ?array $flashOnly = null): array
Recebe uma instância FormRequest pronta e retorna validated() no sucesso. Na falha, grava o primeiro erro e redireciona; null repassa todo input, um array limita os campos e [] não repassa nenhum. Para API, use o caminho JSON do ApiController/FormRequest em vez do redirect Web.
$form = new \App\Http\Requests\Auth\LoginRequest();
$data = $this->validateRequest($form, '/auth/login', ['email']);abort(int $code, string $message = ''): never, abortIf(mixed $condition, int $code, string $message = ''): void, abortUnless(mixed $condition, int $code, string $message = ''): void: lançam RuntimeException contendo o código solicitado. Atenção: no dispatch atual, o Router captura qualquer Throwable da action/middleware e emite 500; não use abort(404) para prometer 404 neste caminho. Uma verificação abortIf(!$user, 404, ...) também produz 500 no estado atual. Corrigir o mapeamento exige mudança no framework, vedada nesta tarefa.Construtores personalizados de Controller devem chamar parent::__construct() antes de usar $this->request; a inicialização da propriedade não é injeção automática. O exemplo intermediário desta página segue esse contrato.