$_GET es un array con la query string de la URL, así que article.php?id=42&lang=en da $_GET['id'] === '42' y $_GET['lang'] === 'en'. $_POST es un array con los campos de un formulario enviado con method="post". Lee los dos con un valor por defecto, $_GET['id'] ?? null, porque la clave falta siempre que falta el parámetro.
Ejecuta el bloque y luego haz clic en los enlaces: cada clic vuelve a ejecutar el script con $_GET rellenado a partir de la query string del enlace.
$_GET['lang'] es lo que diga la URL, no solo los tres enlaces que imprimiste. Cualquiera puede escribir ?lang=<script> en la barra de direcciones, y por eso el bloque busca el valor en $languages en lugar de imprimirlo, y escapa el único lugar donde sí imprime datos de la petición.
Leer un número de la query string
Todos los valores de $_GET son cadenas. Para un número de página, valida y convierte en un solo paso con filter_var() y usa un valor por defecto cuando el valor falte, no sea un número o esté fuera de rango. Recorre las páginas y luego prueba los enlaces Page 999 y Page abc.
filter_var() devuelve el entero 3 para "3" y la opción default para cualquier otra cadena, así que $page es siempre un int utilizable. La página de filter_var enumera los demás validadores.
Leer los datos de un formulario con $_POST
Un formulario con method="post" envía sus campos en el cuerpo de la petición, y PHP los pone en $_POST bajo el name de cada input. $_SERVER['REQUEST_METHOD'] te dice si la petición actual es la primera visita (GET) o un envío (POST). Rellena el formulario y pulsa Send para ver los dos casos.
Un input de texto vacío se envía igualmente, como "", así que tras un envío $_POST['title'] existe aunque el visitante no haya escrito nada. En un servidor REQUEST_METHOD siempre está definido; el ?? 'GET' solo evita avisos cuando ejecutas el archivo con php en la línea de comandos. El patrón completo para validar y volver a mostrar un formulario está en la página de formularios.
Un formulario de búsqueda con method="get"
Usa GET para un formulario cuyo resultado deba ser una URL que se pueda compartir, como un buscador. El navegador convierte los campos en una query string (?q=sort&level=beginner) y el script los lee de $_GET, exactamente igual que un enlace. Busca array o string.
Construir enlaces con http_build_query
Escribir "?q=$q&page=2" a mano falla en cuanto $q contiene un espacio, un & o un #. http_build_query() codifica cada valor por ti, y el resultado pasa por htmlspecialchars() cuando acaba en un href, porque & debe ser & dentro de HTML.
parse_str() con dos argumentos es como PHP construye $_GET a partir de una query string, así que es útil para probar. Pasa siempre el segundo argumento; la antigua forma con un solo argumento, que creaba variables, se eliminó en PHP 8.
$_REQUEST y por qué evitarlo
$_REQUEST es $_GET y $_POST mezclados en un solo array. Los php.ini que trae PHP fijan request_order = "GP", así que cuando los dos contienen la misma clave, gana POST; sin ese ajuste, también se mezclan las cookies:
<?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 cómodo, pero oculta de dónde vino un valor. Un manejador que borra un registro según $_REQUEST['id'] se puede disparar con un simple enlace, justo lo que las acciones solo por POST están pensadas para impedir. Lee $_GET o $_POST por su nombre.
GET vs POST: cuál usar
| GET | POST | |
|---|---|---|
| Por dónde viajan los datos | En la URL: ?q=php&page=2 | En el cuerpo de la petición |
| Se leen con | $_GET | $_POST |
| Favoritos, compartir, botón atrás | Sí | No (el navegador pide reenviar) |
| Longitud | Limitada por la URL (unos pocos miles de caracteres es seguro) | Limitada por post_max_size (8M por defecto) |
| Subida de archivos | No | Sí, con enctype="multipart/form-data" (lee $_FILES) |
| Úsalo para | Búsqueda, filtros, ordenación, paginación | Inicio de sesión, registro, guardar, borrar, pagos |
La regla que importa: una petición GET no debe cambiar nada. Los navegadores precargan enlaces, los rastreadores los siguen y la gente los comparte, así que un enlace ?delete=5 acabará siendo seguido por algo que no pretendía borrar. Ninguno de los dos métodos está cifrado por sí solo: HTTPS protege a los dos, y POST solo mantiene los datos fuera de la URL, del historial del navegador y de los logs del servidor.
Preguntas frecuentes
¿Cómo obtengo un parámetro de la URL en PHP?
Léelo de $_GET con un valor por defecto: para page.php?id=42, $id = $_GET['id'] ?? null; da la cadena "42". Todos los valores son cadenas (o un array con id[]=), así que conviértelo y valídalo, por ejemplo con filter_var($id, FILTER_VALIDATE_INT).
¿Cuál es la diferencia entre $_GET y $_POST?
$_GET viene de la query string de la URL, así que es visible, se puede guardar en favoritos y tiene una longitud limitada; úsalo para búsquedas, filtros y páginas. $_POST viene del cuerpo de la petición de un formulario enviado con method="post"; úsalo para todo lo que cambia datos, como guardar, comprar o iniciar sesión.
¿Cómo compruebo si existe un parámetro GET en PHP?
Usa isset($_GET['q']), que es falso cuando la clave falta o es null. Para tratar también un valor vacío (?q=) como ausente, compara el valor recortado: trim($_GET['q'] ?? '') !== ''.
¿Debo usar $_REQUEST en PHP?
Normalmente no. $_REQUEST mezcla $_GET y $_POST (y, según request_order, las cookies), así que no puedes saber de dónde vino un valor, y un enlace puede aportar un valor que esperabas de un formulario. Lee $_GET o $_POST de forma explícita.
¿Cómo compruebo si una petición es GET o POST en PHP?
Compara $_SERVER['REQUEST_METHOD']: if ($_SERVER['REQUEST_METHOD'] === 'POST') { ... }. Es más fiable que isset($_POST['submit']), que falla cuando el botón no tiene name o cuando el formulario lo envía JavaScript u otro script sin ese campo.