Como obter o URL completo em PHP sem enlouquecer?
\n\nTodo desenvolvedor PHP já enfrentou a tarefa: "Como obtenho o URL completo da página atual?". Parece simples — pegue $_SERVER['HTTP_HOST'], adicione $_SERVER['REQUEST_URI'] — e pronto. Mas a realidade, como sempre, traz suas complicações. HTTP ou HTTPS? E se a porta não for padrão? E se o site estiver atrás de um proxy? E se não for apenas obter, mas fazer isso rapidamente, sem vazamentos de memória e com margem para o futuro?
A pergunta "Get the full URL in PHP" no Stack Overflow acumulou milhares de visualizações e dezenas de respostas. Não é por acaso: o tema parece simples, mas as armadilhas são muitas. Hoje vamos abordar não apenas "como fazer", mas como fazer corretamente, rápido e de forma confiável. Vamos lá!
\n\nPor que copiar diretamente de $_SERVER é ruim?
\n\nDesenvolvedores iniciantes frequentemente escrevem assim:
\n\n$url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];\n\nÀ primeira vista, funciona. Mas vejamos os problemas:
\n- \n
- Sem HTTPS. Se o site usa HTTPS, você obterá
http://— e o navegador reclamará de conteúdo misto. \n - Porta. Se a porta não for padrão (ex.: 8080), ela será perdida se não usar
$_SERVER['SERVER_PORT']. \n - Proxy e balanceadores. Atrás de um proxy reverso (Nginx, Cloudflare),
$_SERVER['HTTP_HOST']pode não ser o que o usuário vê. \n - Segurança. O valor de
HTTP_HOSTpode ser manipulado por um invasor (injeção de cabeçalho Host). \n
Resumindo, copiar e colar da primeira resposta no Stack Overflow não é a melhor opção. Vamos escrever uma função correta e eficiente.
\n\nFunção de referência: obtendo o URL completo corretamente
\n\nAqui está uma função confiável que considera todos os cenários principais:
\n\nfunction getFullUrl(): string {\n $protocol = 'http';\n if (\n (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')\n || (int)$_SERVER['SERVER_PORT'] === 443\n ) {\n $protocol = 'https';\n }\n\n // Considera cabeçalhos de proxy (se confiável)\n $host = $_SERVER['HTTP_HOST'] ?? '';\n if (empty($host) && !empty($_SERVER['SERVER_NAME'])) {\n $host = $_SERVER['SERVER_NAME'];\n }\n\n // Verificação de porta\n $port = (int)$_SERVER['SERVER_PORT'];\n $portSuffix = '';\n if (\n ($protocol === 'http' && $port !== 80)\n || ($protocol === 'https' && $port !== 443)\n ) {\n $portSuffix = ':' . $port;\n }\n\n $uri = $_SERVER['REQUEST_URI'] ?? '/';\n\n return $protocol . '://' . $host . $portSuffix . $uri;\n}\n\nO que é importante aqui?
\n- \n
- Verificamos
HTTPS— método padrão, funciona em 99% dos casos. \n - Consideramos
SERVER_PORT— se o site estiver em porta não padrão, não a perdemos. \n - Opção alternativa via
SERVER_NAME— casoHTTP_HOSTesteja vazio. \n - Não usamos
$_SERVER['SCRIPT_URI']— não está disponível em todos os lugares. \n
Otimização de desempenho: quando cada milissegundo conta
\n\nSe você chama essa função em cada página ou em um loop, vale a pena pensar na velocidade. Aqui estão algumas dicas:
\n\n1. Cache do resultado
\nSe o URL não muda dentro de uma mesma requisição (e não muda), faça cache:
\n\nfunction getFullUrlCached(): string {\n static $url = null;\n if ($url === null) {\n $url = getFullUrl(); // usa nossa função acima\n }\n return $url;\n}\n\nUma variável estática mantém o valor após a primeira chamada — sem recálculos desnecessários.
\n\n2. Evite operações desnecessárias
\nNão use filt