O $_GET é um array da query string da URL, então article.php?id=42&lang=en dá $_GET['id'] === '42' e $_GET['lang'] === 'en'. O $_POST é um array dos campos de um formulário enviado com method="post". Leia os dois com um padrão, $_GET['id'] ?? null, porque a chave falta sempre que o parâmetro falta.
Rode o bloco e clique nos links: cada clique executa o script de novo com $_GET preenchido pela query string do link.
$_GET['lang'] é o que a URL disser, não só os três links que você imprimiu. Qualquer pessoa pode digitar ?lang=<script> na barra de endereço, e é por isso que o bloco procura o valor em $languages em vez de imprimi-lo, e escapa o único lugar em que imprime dados da requisição.
Ler um número da query string
Todo valor em $_GET é uma string. Para um número de página, valide e converta num passo com filter_var() e use um padrão quando o valor estiver ausente, não for número ou estiver fora do intervalo. Navegue pelas páginas e depois teste os links Page 999 e Page abc.
O filter_var() retorna o inteiro 3 para "3" e a opção default para qualquer outra string, então $page é sempre um int utilizável. A página sobre filter_var lista os outros validadores.
Ler dados de formulário com $_POST
Um formulário com method="post" envia os campos no corpo da requisição, e o PHP os coloca em $_POST sob o name de cada input. $_SERVER['REQUEST_METHOD'] diz se a requisição atual é a primeira visita (GET) ou um envio (POST). Preencha o formulário e clique em Send para ver os dois.
Um input de texto vazio ainda é enviado, como "", então depois de um envio $_POST['title'] existe mesmo que o visitante não tenha digitado nada. Num servidor, REQUEST_METHOD está sempre definido; o ?? 'GET' só deixa o script quieto quando você roda o arquivo com php na linha de comando. O padrão completo para validar e reexibir um formulário está na página sobre formulários.
Um formulário de busca com method="get"
Use GET para um formulário cujo resultado deve ser uma URL compartilhável, como uma caixa de busca. O navegador transforma os campos numa query string (?q=sort&level=beginner) e o script os lê de $_GET, exatamente como num link. Busque por array ou string.
Montar links com http_build_query
Escrever "?q=$q&page=2" à mão quebra assim que $q contém um espaço, & ou #. O http_build_query() codifica cada valor para você, e o resultado passa pelo htmlspecialchars() quando vai para um href, porque & deve ser & dentro do HTML.
O parse_str() com dois argumentos é como o PHP monta o $_GET a partir de uma query string, então é prático para testes. Sempre passe o segundo argumento; a forma antiga com um argumento, que criava variáveis, foi removida no PHP 8.
$_REQUEST e por que evitá-lo
O $_REQUEST é $_GET e $_POST juntos num array. Os arquivos php.ini que vêm com o PHP definem request_order = "GP", então quando os dois contêm a mesma chave, o POST vence; sem essa configuração, os cookies também entram:
<?php
// POST /save.php?id=1 with a form field id=2
echo $_GET['id']; // "1"
echo $_POST['id']; // "2"
echo $_REQUEST['id']; // "2"
Parece prático, mas esconde de onde veio um valor. Um handler que apaga um registro com base em $_REQUEST['id'] pode ser acionado por um simples link, que é exatamente o que as ações só com POST querem impedir. Leia $_GET ou $_POST pelo nome.
GET ou POST: qual usar
| GET | POST | |
|---|---|---|
| Onde os dados trafegam | Na URL: ?q=php&page=2 | No corpo da requisição |
| Leia com | $_GET | $_POST |
| Favorito, compartilhar, botão voltar | Sim | Não (o navegador pede para reenviar) |
| Tamanho | Limitado pela URL (alguns milhares de caracteres é seguro) | Limitado pelo post_max_size (8M por padrão) |
| Upload de arquivos | Não | Sim, com enctype="multipart/form-data" (leia $_FILES) |
| Use para | Busca, filtros, ordenação, paginação | Login, cadastro, salvar, apagar, pagamentos |
A regra que importa: uma requisição GET não deve alterar nada. Navegadores fazem prefetch de links, crawlers os seguem e pessoas os compartilham, então um link ?delete=5 uma hora vai ser seguido por algo que não queria apagar. Nenhum dos dois métodos é criptografado por si só: o HTTPS protege os dois, e o POST só mantém os dados fora da URL, do histórico do navegador e dos logs do servidor.
Perguntas frequentes
Como pego um parâmetro da URL no PHP?
Leia de $_GET com um padrão: para page.php?id=42, $id = $_GET['id'] ?? null; dá a string "42". Todo valor é uma string (ou um array para id[]=), então converta e valide, por exemplo com filter_var($id, FILTER_VALIDATE_INT).
Qual a diferença entre $_GET e $_POST?
O $_GET vem da query string da URL, então é visível, pode virar favorito e tem tamanho limitado; use para buscas, filtros e páginas. O $_POST vem do corpo da requisição de um formulário enviado com method="post"; use para tudo o que altera dados, como salvar, comprar ou fazer login.
Como verifico se um parâmetro GET existe no PHP?
Use isset($_GET['q']), que é falso quando a chave não existe ou é null. Para também tratar um valor vazio (?q=) como ausente, compare o valor com trim: trim($_GET['q'] ?? '') !== ''.
Devo usar $_REQUEST no PHP?
Normalmente não. O $_REQUEST junta $_GET e $_POST (e, dependendo do request_order, os cookies), então você não sabe de onde veio um valor, e um link pode fornecer um valor que você esperava de um formulário. Leia $_GET ou $_POST explicitamente.
Como verifico se uma requisição é GET ou POST no PHP?
Compare $_SERVER['REQUEST_METHOD']: if ($_SERVER['REQUEST_METHOD'] === 'POST') { ... }. Isso é mais confiável que isset($_POST['submit']), que falha quando o botão não tem name ou quando o formulário é enviado por JavaScript ou outro script sem esse campo.