Redirecionamentos em PHP: como fazer

Redirecionamentos em PHP: como fazer
Se você trabalha com PHP, mais cedo ou mais tarde vai precisar enviar o visitante de uma URL para outra: depois de salvar um formulário, quando uma página muda de endereço ou quando quer proteger uma área privada do seu site. Essa ação é chamada de redirecionamento ou redirect, e é uma das tarefas mais comuns no desenvolvimento web. Neste artigo mostramos como fazer um redirect em PHP da forma correta: o que é um redirecionamento, para que serve, como usar a header() com Location, qual é a diferença entre um 301 e um 302 e quais são os erros mais comuns que você deve evitar. Vamos direto ao ponto, com explicações claras e exemplos de código prontos para testar. Se você quer apenas a resposta curta: em PHP, um redirect é feito enviando o cabeçalho HTTP Location com a função header() e interrompendo a execução com exit. Mas, como em tudo que envolve HTTP, os detalhes importam: o momento em que a função é chamada, o código de status que a acompanha e o tratamento da saída do script fazem a diferença entre um redirecionamento que funciona e um incômodo aviso de headers already sent na tela.O que é um redirecionamento em PHP
Para entender os redirecionamentos em PHP, primeiro é preciso lembrar como a web funciona. Quando o navegador solicita uma página, o servidor responde com uma mensagem HTTP composta de três partes: a linha de status com um código (por exemplo 200 OK), um conjunto de cabeçalhos ou headers e, opcionalmente, o corpo com o HTML. O PHP é o programa que roda no servidor e constrói essa resposta. Um redirecionamento nada mais é do que uma resposta HTTP especial: em vez de devolver o conteúdo da página, o servidor envia um cabeçalho Location com a URL para onde o navegador deve ir e um código de status que indica se a mudança é permanente ou temporária. O navegador recebe essa resposta, lê a nova URL e faz uma segunda requisição automaticamente. Para o usuário tudo parece instantâneo: ele digita um endereço e cai em outro. Essa é a forma correta e a que os mecanismos de busca usam. Existem outras técnicas para levar o usuário a outra página, como a tag meta de refresh do HTML ou o JavaScript com window.location, mas nenhuma substitui um redirecionamento HTTP real quando você precisa mover uma URL, preservar o ranqueamento ou proteger uma rota: o redirecionamento com PHP acontece no servidor, antes de enviar uma única linha de HTML.Para que serve um redirect em PHP
Existem muitos cenários em que uma página precisa responder com um redirecionamento em PHP. Os mais comuns são:- A página mudou de endereço: se você reorganiza a estrutura do site, migra para outro domínio ou remove uma página, redireciona a URL antiga para a nova para que ninguém encontre um erro 404.
- URLs amigáveis e canônicas: com redirecionamentos você unifica as variantes de uma mesma página, por exemplo de http para https, de www para sem www ou de index.php para a raiz, para que todo o tráfego e o SEO apontem para uma única URL.
- Depois de enviar um formulário: quando um formulário salva dados, o correto é responder com um redirecionamento para uma página de confirmação em vez de HTML direto; assim, se o usuário atualizar a página, o navegador não reenvia o formulário nem duplica o pedido. É o padrão PRG que veremos adiante.
- Redirect 301 para SEO: um 301 informa ao Google que a página mudou de forma definitiva e transfere a maior parte da autoridade da URL antiga para a nova.
- Proteger o acesso: se uma página exige login ou um papel específico, o script redireciona o visitante para a tela de login quando a condição não é atendida.
Como fazer um redirect em PHP com header e Location
A função fundamental é a header(), que envia um cabeçalho HTTP bruto. Para redirecionar, você envia o cabeçalho Location com a URL de destino. O exemplo mais simples de um redirect em PHP é este:- <?php
- // Redireciona o navegador para outra URL
- header("Location: https://www.exemplo.com/nova-pagina");
- exit;
Redirect 301 vs 302: permanente ou temporário
Nem todos os redirecionamentos significam a mesma coisa. O código de status HTTP que acompanha o Location informa ao navegador e aos buscadores se a mudança é definitiva ou passageira, e isso tem consequências práticas:| Código | Nome | Quando usar |
|---|---|---|
| 301 | Moved Permanently | A página mudou para sempre: os buscadores atualizam a URL, o SEO é preservado e os favoritos dos usuários são atualizados. |
| 302 | Found | A mudança é temporária: manutenção, promoções ou mudanças de curta duração. Os buscadores mantêm a URL original. |
| 303 | See Other | Depois de processar um formulário enviado com POST: o navegador faz uma requisição GET para a página de confirmação (padrão PRG). |
| 307 | Temporary Redirect | Como o 302, mas preservando o método HTTP: se a requisição foi POST, a repetição também será POST. |
- header("Location: https://www.exemplo.com/nova-pagina", true, 301);
- exit;
- http_response_code(301);
- header("Location: https://www.exemplo.com/nova-pagina");
- exit;
Padrão PRG: redirecionar depois de enviar um formulário
Um dos usos mais valiosos do redirect em PHP é o padrão Post/Redirect/Get, conhecido como PRG. O problema que ele resolve é clássico: um formulário de pedido, cadastro ou contato envia seus dados com POST e o servidor os processa. Se o script responder imprimindo a página de confirmação, o navegador mantém a requisição POST no histórico; quando o usuário aperta F5 ou volta na página, o navegador pergunta se ele quer reenviar o formulário e, se ele aceitar, o pedido é processado duas vezes. A solução PRG é que o script que recebe o POST não devolva HTML: depois de validar e salvar os dados, ele responde com um redirecionamento, normalmente 303 See Other, para uma página acessada por GET. Assim, ao atualizar, apenas a página de confirmação é recarregada, sem efeitos colaterais:- <?php
- // salvar_pedido.php: recebe o formulário via POST
- if ($_SERVER["REQUEST_METHOD"] === "POST") {
- // aqui você valida e salva o pedido
- salvar_pedido($_POST);
- // 303 para que a atualização não repita o envio
- header("Location: /pedido-confirmado.php", true, 303);
- exit;
- }
Redirect condicional: proteger páginas e escolher o destino
Um redirecionamento em PHP quase nunca é uma linha solta: normalmente ele depende de uma condição. O caso típico é proteger uma página privada. Se o usuário não fez login, ele é redirecionado para a tela de login antes de ver qualquer conteúdo:- <?php
- session_start();
- // se não há sessão ativa, o visitante vai para o login
- if (!isset($_SESSION["usuario"])) {
- header("Location: /login.php");
- exit;
- }
- // o restante da página só executa com sessão ativa
- <?php
- // destinos permitidos
- $secoes = array(
- "perfil" => "/perfil.php",
- "pedidos" => "/pedidos.php",
- "ajuda" => "/ajuda.php"
- );
- $chave = $_GET["ir"] ?? "perfil";
- if (isset($secoes[$chave])) {
- header("Location: " . $secoes[$chave]);
- exit;
- }
- // se a chave não existe, vai para a página inicial
- header("Location: /inicio");
- exit;
Redirecionar com atraso
Às vezes você não quer pular de imediato, mas mostrar uma mensagem e levar o usuário para a nova página alguns segundos depois. A forma simples é o cabeçalho Refresh, que, embora não faça parte do padrão HTTP, é compatível com todos os navegadores:- header("Refresh: 5; url=https://www.exemplo.com/nova-pagina");
- echo "Você será redirecionado para a nova página em 5 segundos...";
- exit;
Erros comuns ao fazer um redirect em PHP
Embora a mecânica seja simples, alguns erros se repetem nos projetos. Conhecê-los vai economizar horas de depuração. 1. O aviso headers already sent. É o erro mais pesquisado do desenvolvimento PHP e aparece quando você chama a header() depois de o script já ter enviado saída. Qualquer coisa conta: um echo, uma linha de HTML, um espaço ou uma quebra de linha fora das tags PHP, e até um BOM invisível de codificação UTF-8 que alguns editores adicionam no início do arquivo. Quando o corpo da resposta já começou a ser enviado, os cabeçalhos não podem ser modificados e o redirecionamento não acontece:- <?php
- echo "Bem-vindo à loja";
- // em um servidor sem buffer de saída, isso já envia HTML
- header("Location: /inicio");
- // Warning: Cannot modify header information - headers already sent
- Coloque a header() e sua lógica no início do script, antes de qualquer saída: estruture o código para decidir o redirecionamento antes de gerar o HTML.
- Omita a tag de fechamento ?> no final dos arquivos que contêm apenas PHP: assim não sobram espaços ou quebras de linha que sejam enviados como saída.
- Se não puder evitar a saída anterior, ative o buffer de saída com ob_start() no início do script; a saída fica retida e a header() pode executar depois.
- Confira se o arquivo não foi salvo com BOM UTF-8, porque esses três bytes invisíveis no início também contam como saída.
- Revise se não há espaços ou linhas em branco antes da tag de abertura <?php.
- <?php
- ob_start(); // a partir daqui, a saída fica no buffer
- // ... qualquer echo ou HTML fica retido ...
- header("Location: /inicio"); // sem conflito agora
- exit;
- curl -I https://www.exemplo.com/pagina-antiga
- HTTP/1.1 301 Moved Permanently
- Location: https://www.exemplo.com/nova-pagina
Em resumo
Fazer um redirect em PHP é simples, mas fazer bem exige entender HTTP. A regra que resume todo o artigo é: header("Location: URL") antes de qualquer saída, com o código de status adequado e seguida de exit.- header() com Location envia o navegador para outra URL e deve ser chamada antes de qualquer saída.
- Sem um código explícito, o PHP responde com um 302 temporário; use o terceiro argumento da header() ou o http_response_code() para enviar 301, 303 e os demais códigos.
- O padrão PRG responde a um POST com um redirect 303 para evitar duplicatas ao atualizar a página.
- Use redirecionamentos condicionais para proteger páginas e sempre valide o destino contra uma lista branca.
- Ao ver o aviso headers already sent, revise a saída anterior, remova o fechamento das tags PHP e teste com ob_start().
- Confira seus redirecionamentos com curl -I para ver o código de status e a URL de destino reais.