HTTP no tiene memoria: cada petición llega al servidor como si fuera la primera. Sesiones y cookies son las dos herramientas que usa PHP para “recordar” a un usuario entre una página y otra: su login, su carrito, su idioma preferido. En el libro PHP desde cero hasta experto aprendes a manejar sesiones, cookies y superglobales junto con los formularios; este artículo explica cómo funcionan y cómo usarlas sin abrir agujeros de seguridad.
Cookies vs sesiones
| Cookie | Sesión | |
|---|---|---|
| Dónde se guarda | En el navegador | En el servidor |
| El usuario puede verla y cambiarla | Sí | No (solo tiene el identificador) |
| Tamaño | Pequeño (unos 4 KB por cookie) | Lo que necesites, con sensatez |
| Duración | La que fijes, incluso meses | Hasta cerrar el navegador o caducar |
| Úsala para | Preferencias: idioma, tema, aviso de cookies aceptado | Login, carrito, datos temporales confiables |
De hecho, una sesión usa una cookie: PHP envía al navegador una cookie llamada
PHPSESSID con un identificador aleatorio, y guarda los datos en el servidor asociados a ese
identificador.
Cookies: crear, leer y borrar
<?php
// Crear: siempre ANTES de imprimir cualquier HTML
setcookie('idioma', 'es', [
'expires' => time() + 60 * 60 * 24 * 365, // un año
'path' => '/',
'secure' => true, // solo por HTTPS
'httponly' => true, // JavaScript no puede leerla
'samesite' => 'Lax',
]);
// Leer: disponible a partir de la SIGUIENTE petición
$idioma = $_COOKIE['idioma'] ?? 'es';
// Validar: el usuario puede poner cualquier valor
if (!in_array($idioma, ['es', 'en', 'pt'], true)) {
$idioma = 'es';
}
// Borrar: misma cookie con fecha en el pasado
setcookie('idioma', '', ['expires' => time() - 3600, 'path' => '/']);
es_admin=1 o el id del usuario
sin firmar. El usuario puede editarla desde las herramientas del navegador en segundos.
Sesiones: el estado en el servidor
<?php
session_start(); // al principio de cada página que use la sesión
$_SESSION['usuario_id'] = 42; // guardar
$id = $_SESSION['usuario_id'] ?? null; // leer
unset($_SESSION['mensaje']); // borrar un dato
// Mensaje "flash": se muestra una sola vez (p. ej., tras guardar un formulario)
if (isset($_SESSION['flash'])) {
echo htmlspecialchars($_SESSION['flash']);
unset($_SESSION['flash']);
}
Ejemplo: un carrito de compras con $_SESSION
El carrito es el ejemplo clásico: el usuario añade productos en distintas páginas y el servidor los recuerda hasta que compra.
<?php
declare(strict_types=1);
session_start();
$_SESSION['carrito'] ??= []; // [id_producto => cantidad]
function agregarAlCarrito(int $id, int $cantidad = 1): void
{
$_SESSION['carrito'][$id] = ($_SESSION['carrito'][$id] ?? 0) + $cantidad;
}
function quitarDelCarrito(int $id): void
{
unset($_SESSION['carrito'][$id]);
}
function totalCarrito(array $precios): float
{
$total = 0;
foreach ($_SESSION['carrito'] as $id => $cantidad) {
$total += ($precios[$id] ?? 0) * $cantidad;
}
return $total;
}
// Las acciones que modifican el carrito llegan por POST
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
if ($id) {
match ($_POST['accion'] ?? '') {
'agregar' => agregarAlCarrito($id),
'quitar' => quitarDelCarrito($id),
default => null,
};
}
header('Location: carrito.php');
exit;
}
Fíjate en que el carrito guarda solo ids y cantidades. Los precios se consultan en la base de datos al mostrar el total, nunca se toman de la sesión ni del formulario: así nadie puede comprar un monitor a un peso.
Seguridad de sesiones y cookies
- Regenera el identificador al iniciar sesión:
session_regenerate_id(true)evita la fijación de sesión. - Configura la cookie de sesión antes de
session_start():
<?php
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'secure' => !empty($_SERVER['HTTPS']),
'httponly' => true,
'samesite' => 'Lax',
]);
ini_set('session.use_strict_mode', '1'); // rechaza ids de sesión inventados
session_start();
- Caducidad por inactividad: guarda la hora del último acceso en la sesión y ciérrala si pasan, por ejemplo, 30 minutos.
- Cierre de sesión completo: vacía
$_SESSION, borra la cookie y llama asession_destroy(). - “Headers already sent”:
session_start()ysetcookie()envían cabeceras, así que deben ir antes de cualquier salida, incluso de un espacio.
Con estas bases puedes construir un login completo y su flujo de recuperación de contraseña.
Formularios, sesiones y cookies a fondo
El libro PHP desde cero hasta experto enseña a procesar formularios y manejar sesiones, cookies y superglobales como $_GET, $_POST y $_SESSION.
Comprar en Amazon