Lección: Formularios HTML y PHP
Los formularios HTML son la vía natural para que los usuarios envíen datos a tus scripts PHP, ya sea para un libro de visitas, un registro, o una búsqueda. En esta lección aprenderás a crear formularios, procesar sus datos con PHP, validarlos, y protegerlos contra problemas comunes.
Introducción
Los formularios HTML permiten a los usuarios introducir datos que tu
script PHP puede procesar. Detrás de muchas aplicaciones PHP (como foros
o tiendas online) hay formularios recolectando datos. Para seguir esta
lección, deberías conocer etiquetas HTML básicas como
<form>
, <input>
, y
<textarea>
.
Cuando un usuario envía un formulario, PHP almacena los datos en
super variables automáticas ($_POST
o $_GET
), listas
para que las uses en tu script.
Nociones básicas
Un formulario HTML se define con la etiqueta
<form>
y sus atributos principales: -
action: La URL del script PHP que procesará los datos
(por ejemplo, form1.php
). - method: El
método de envío, post
(datos ocultos en la solicitud) o
get
(datos visibles en la URL).
Dentro del formulario, elementos como <input>
,
<textarea>
, o <select>
tienen un
atributo name
. Cuando se envía el formulario, PHP crea
variables con esos nombres y los valores introducidos por el
usuario.
Ejemplo de formulario (libro de visitas):
<form action="form1.php" method="post">
Nombre: <input type="text" name="nombre" size="20" /><br>
Escribe tu mensaje:<br>
<textarea name="mensaje" cols="40" rows="7"></textarea><br>
Tu web: <input type="text" name="url" size="20" /><br>
<input type="submit" name="enviar" value="Click para enviar" />
</form>
Vista renderizada:
Métodos: POST vs. GET
- POST: Los datos se envían en el cuerpo de la solicitud, no visibles en la URL. Ideal para datos sensibles o largos (por ejemplo, mensajes, contraseñas).
- GET: Los datos se añaden a la URL (por ejemplo,
?nombre=Juan
). Útil para búsquedas o enlaces, pero limitado en tamaño y menos seguro.
Ejemplo con GET
:
<form action="buscar.php" method="get">
Buscar: <input type="text" name="query" />
<input type="submit" value="Buscar" />
</form>
URL resultante: buscar.php?query=php
Procesando formularios en PHP
Los datos del formulario se almacenan en los arrays globales
$_POST
o $_GET
, según el método. Por ejemplo,
para el formulario anterior, el script form1.php
podría
ser:
<?php
declare(strict_types=1);
// Define constantes para nombres de campos
const CAMPO_NOMBRE = "nombre";
const CAMPO_MENSAJE = "mensaje";
const CAMPO_URL = "url";
// Verifica si se envió el formulario
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$nombre = $_POST[CAMPO_NOMBRE] ?? "";
$mensaje = $_POST[CAMPO_MENSAJE] ?? "";
$url = $_POST[CAMPO_URL] ?? "";
echo "Nombre: " . htmlspecialchars($nombre) . "\n";
echo "Mensaje: " . htmlspecialchars($mensaje) . "\n";
echo "URL: " . htmlspecialchars($url) . "\n";
}
?>
Notas: - Usa htmlspecialchars()
para
evitar ataques XSS (por ejemplo, scripts maliciosos en
<textarea>
). - Verifica
$_SERVER["REQUEST_METHOD"]
para procesar solo envíos
válidos. - Usa constantes para nombres de campos, mejorando la
mantenibilidad.
Validando datos
Siempre valida los datos del formulario para evitar errores o ataques:
<?php
declare(strict_types=1);
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$nombre = filter_input(INPUT_POST, "nombre", FILTER_SANITIZE_STRING) ?? "";
$mensaje = filter_input(INPUT_POST, "mensaje", FILTER_SANITIZE_STRING) ?? "";
$url = filter_input(INPUT_POST, "url", FILTER_SANITIZE_URL) ?? "";
// Forzar tipo string para seguridad
$nombre = (string)$nombre;
// Validaciones
if (empty($nombre)) {
echo "El nombre es obligatorio\n";
} elseif (strlen($nombre) > 50) {
echo "El nombre es demasiado largo\n";
} else {
echo "Datos válidos: " . htmlspecialchars($nombre) . "\n";
}
}
?>
Notas: - Usa filter_input()
para
sanitizar datos. - (string)
asegura que los datos sean
tratados como cadenas. - Verifica campos vacíos y límites (por ejemplo,
longitud máxima).
Evitar ataques CSRF (Cross-Site Request Forgery)
Un token CSRF protege tu formulario contra ataques que intentan enviarlo desde otra página maliciosa. Se genera un valor aleatorio y único que se guarda en la sesión, y se espera que llegue con cada formulario enviado.
Para implementar un token CSRF:
- Genera un token único y guárdalo en la sesión.
- Incluye el token en un campo oculto del formulario.
- Al recibir el formulario, verifica que el token enviado coincida con el de la sesión.
Si el token no coincide, detén el script para evitar ataques.
Ejemplo de implementación: creamos el token:
<?php
session_start();
// Creamos un token único y lo guardamos en la sesión
$_SESSION["csrf_token"] = bin2hex(random_bytes(32)); ?>
<form action="form1.php" method="post">
<!-- Campo oculto con el token de seguridad -->
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>" />
<!-- Aquí irían los demás campos del formulario --> </form>
Verificamos el token al recibir el formulario:
<?php
session_start();
// Verificamos que el token recibido coincida con el de la sesión
if (!isset($_POST["csrf_token"], $_SESSION["csrf_token"]) || $_POST["csrf_token"] !== $_SESSION["csrf_token"])
{
// Si no coincide, detenemos el script por seguridad
die("Error de seguridad: token CSRF inválido.");
}
// Si el token es correcto, el formulario es legítimo y podemos continuar
?>
Ejemplo completo
index.php:
<!DOCTYPE html>
<html>
<head>
<title>Libro de Visitas</title>
<style>
label { display: block; margin: 10px 0; }
input, textarea { margin-left: 10px; }
</style>
</head>
<body>
<h1>Libro de Visitas</h1>
<form action="index.php" method="post">
<label>Nombre: <input type="text" name="nombre" size="20" /></label>
<label>Mensaje:<br><textarea name="mensaje" cols="40" rows="7"></textarea></label>
<label>Web: <input type="text" name="url" size="20" /></label>
<input type="submit" name="enviar" value="Enviar" />
</form>
<?php
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$nombre = filter_input(INPUT_POST, "nombre", FILTER_SANITIZE_STRING) ?? "";
$mensaje = filter_input(INPUT_POST, "mensaje", FILTER_SANITIZE_STRING) ?? "";
$url = filter_input(INPUT_POST, "url", FILTER_SANITIZE_URL) ?? "";
if (empty($nombre) || empty($mensaje)) {
echo "<p style='color: red;'>Nombre y mensaje son obligatorios</p>";
} else {
echo "<h2>Entrada registrada:</h2>";
echo "<p>Nombre: " . htmlspecialchars($nombre) . "</p>";
echo "<p>Mensaje: " . htmlspecialchars($mensaje) . "</p>";
echo "<p>Web: " . htmlspecialchars($url) . "</p>";
}
}
?>
</body>
</html>
Explicación: - El formulario y el procesamiento
están en el mismo archivo (index.php
). - Valida campos
obligatorios y sanitiza entradas. - Muestra los datos procesados con
htmlspecialchars()
.