Skip to content

Formularios en PHP ​

Contenidos

Introducción ​

Un programa necesita interactuar con el usuario. Para ello dos de las típicas instruccines son:

  1. Leer valores proporcionados por el usuario.
  2. Mostrar los resultados obtenidos.

En PHP ya conocemos echo y print, que permiten generar contenido en la respuesta que el servidor envía al navegador. Además de estas primitivas hay otras funciones prìntf

Diagrama de InteracutandoPrograma
Imagen personal retocada con IA

Cómo leer datos del usuario ​

Estamos desarrollando una aplicación web: esto tiene implicaciones, como ya hemos comentado. el código PHP se ejecuta en el servidor cuando el navegador solicita un recurso.

Por eso, no podemos detener un script PHP que se está ejecutando en el servidor, esperando que el usuario escriba en el navegador, como haríamos en una aplicación de escritorio.

Pero tenemos la necesidad de que un usuario, pueda enviar valores para la ejecución de un script.

Solución (hay más opciones):

El navegador envía los valores junto con una nueva petición HTTP, y esto lo vamos a conseguir con los formulario HTML.
Diagrama de FormularioPHP
El proceso
  1. El usuario rellena los campos del formulario (input, select, textarea...).
  2. Al pulsar el botón de envío (submit), el navegador realiza una petición al servidor.
  3. Cada campo enviado aporta un nombre y un valor; el nombre se indica con el atributo name.
  4. PHP permite consultar los datos mediante $_GET o $_POST, según el método empleado.

Creando un formulario ​

Formulario HTML
  • Un formulario es un elemento HTML, contenedor
  • Se delimitada por <form>,
  • Su objetivo es contener otros elementos de entrada de valores
  • El usuario puede introducir o seleccionar valores para enviarlos al servidor.
Atributos de `form`

De los atributos de atributos de form , nos interesan especialmente dos:

  • action: URL del recurso al que se enviará el formulario, por ejemplo datos.php.
  • method: método HTTP utilizado para el envío, habitualmente GET o POST.

El atributo action ​

html
<form action="datos.php" method="POST">
    <!-- Campos del formulario -->
    <button type="submit">Enviar</button>
</form>

Si indicamos datos.php, el navegador resuelve esa ruta respecto de la URL de la página actual. También podemos utilizar una ruta absoluta, como /pruebas/datos.php.

Actividad

Ping-pong entre páginas

Crea dos archivos, pin.php y pon.php. Ambos tendrán un botón de envío: desde pin.php iremos a pon.php y desde pon.php volveremos a pin.php.

Posible solución

pin.php

html
<!doctype html>
<html lang="es">
<head><meta charset="UTF-8"><title>Pin</title></head>
<body>
    <form action="pon.php">
        <input type="submit" value="Ir a pon">
    </form>
</body>
</html>

pon.php

html
<!doctype html>
<html lang="es">
<head><meta charset="UTF-8"><title>Pon</title></head>
<body>
    <form action="pin.php">
        <input type="submit" value="Ir a pin">
    </form>
</body>
</html>

Contenido protegido

Introduce la contraseña para ver el contenido.

El atributo method: GET o POST ​

Métodos de envío
  • GET: los datos del formulario se codifican normalmente en la cadena de consulta de la URL (?nombre=...).
  • POST: los datos se envían normalmente en el cuerpo de la petición HTTP.
html
<form action="datos.php" method="GET">...</form>
<form action="datos.php" method="POST">...</form>

Si no se indica method, el valor predeterminado es GET.

Método GET: ejemplo
html
<form action="datos.php" method="GET">
    <label for="nombre">Nombre</label>
    <input type="text" id="nombre" name="nombre" value="María">

    <label for="apellido">Apellido</label>
    <input type="text" id="apellido" name="apellido" value="Ruiz">

    <input type="submit" value="Enviar">
</form>

Formulario con nombre y apellido

Al enviarlo, el navegador solicitará una URL similar a:

text
datos.php?nombre=Mar%C3%ADa&apellido=Ruiz

El signo ? inicia los parámetros y & separa las parejas nombre=valor. El navegador codifica los caracteres especiales para incluirlos en la URL.

Parámetros GET en la URL

El atributo name identifica el dato enviado al servidor; id identifica el elemento dentro del documento HTML y permite, por ejemplo, asociarlo a un <label> o seleccionarlo desde JavaScript. El atributo value establece su valor inicial.

GET, POST y seguridad

POST no cifra los datos ni es intrínsecamente más seguro que GET. Para proteger la información durante el transporte debemos utilizar HTTPS. No envíes contraseñas ni otros secretos en la URL: pueden quedar registrados en el historial y en los registros del servidor.

Podemos inspeccionar los datos enviados desde las herramientas de desarrollo del navegador, en la pestaña Red / Network.

Datos de una petición POST

Otro atributo importante es enctype, que determina cómo se codifica el cuerpo de un formulario. Para subir archivos suele utilizarse enctype="multipart/form-data" junto con method="POST"; no es un mecanismo de cifrado.

Elementos del formulario ​

Los formularios pueden contener input, button, select, textarea y otros elementos. Algunos tipos habituales de input son text, password, email, date, radio, checkbox, hidden, file y submit.

  • type: tipo de control.
  • name: nombre con el que se envía su valor.
  • value: valor inicial o valor asociado al control.
  • type="hidden": campo que no se muestra visualmente, pero cuyo valor se envía con el formulario. No es secreto ni fiable por sí mismo: el usuario puede modificarlo.

Consulta la documentación de formularios de MDN.

Formulario para solicitar un número
html
<!doctype html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Tabla de multiplicar</title>
</head>
<body>
    <form action="tabla.php" method="GET">
        <label for="numero">Inserta un número</label>
        <input type="text" id="numero" name="numero">
        <input type="submit" value="Enviar">
    </form>
</body>
</html>

Formulario de un número

En tabla.php podemos leer el dato recibido mediante $_GET['numero']. Como aún no sabemos si existe, conviene comprobarlo antes de utilizarlo:

php
<?php
$numero = $_GET['numero'] ?? '';
echo 'Valor introducido: ' . htmlspecialchars($numero, ENT_QUOTES, 'UTF-8');

Obtener datos de un formulario ​

PHP dispone de las variables superglobales $_GET y $_POST, que son arrays asociativos. Sus índices corresponden a los atributos name de los controles enviados.

html
<form action="resuelve.php" method="POST">
    <input type="text" name="nombre">
    <input type="submit" value="Enviar">
</form>

En resuelve.php:

php
<?php
$nombre = $_POST['nombre'] ?? '';

Existe también $_REQUEST, pero no se recomienda para estos ejemplos: puede combinar datos procedentes de GET, POST y cookies, según la configuración, y hace menos explícito su origen.

Comprobar si una variable existe ​

En PHP es importante distinguir entre una variable inexistente, una variable con valor null y una variable que contiene un valor considerado «vacío».

Pregunta

¿Qué ocurre con `$edad;`?

Escribir únicamente $edad; no declara ni inicializa la variable. Intentar leer una variable indefinida genera un aviso (Warning en PHP actual). Para inicializarla a nulo debemos escribir $edad = null;.

Las funciones y construcciones más útiles son:

ComprobaciónSignificado
isset($variable)true si está definida y su valor no es null
empty($variable)true si no existe o contiene un valor considerado vacío
is_null($variable)true si su valor es null; requiere que la variable exista para evitar avisos
php
<?php
$variable = null;
var_dump(isset($variable));   // false
var_dump(empty($variable));   // true
var_dump(is_null($variable)); // true

$variable = 0;
var_dump(isset($variable));   // true
var_dump(empty($variable));   // true
var_dump(is_null($variable)); // false
Valores considerados vacíos

empty() considera vacíos, entre otros, "", 0, 0.0, "0", false, null y []. No confundas un campo vacío con un campo cuyo valor es cero.

Actividad

Probando valores

Modifica $variable en el ejemplo anterior y prueba con null, "", 0, "0", true y false. Compara los resultados de isset(), empty() e is_null().

Actividad

Comprobar un dato del formulario

Realiza una página con una caja de texto. Si el usuario no introduce ningún valor, muéstrale un aviso; en caso contrario, muestra el valor recibido. El texto "0" debe aceptarse como valor válido.

Posible solución: form1.php
php
<?php
$mensaje = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $valor = $_POST['valor'] ?? '';
    if (trim($valor) === '') {
        $mensaje = 'Debes introducir un valor';
    } else {
        $mensaje = 'Has introducido: ' . $valor;
    }
}
?>
<!doctype html>
<html lang="es">
<head><meta charset="UTF-8"><title>Formulario</title></head>
<body>
    <p><?= htmlspecialchars($mensaje, ENT_QUOTES, 'UTF-8') ?></p>
    <form action="form1.php" method="POST">
        <fieldset>
            <legend>Inserta datos</legend>
            <input type="text" name="valor">
            <input type="submit" value="Enviar">
        </fieldset>
    </form>
</body>
</html>

Validar valores en el servidor ​

Aunque el navegador valide los campos, siempre debemos comprobar los datos en el servidor. Los valores de los controles de texto llegan normalmente como cadenas, incluso cuando representan números.

php
<?php
$valor = '754';
var_dump(is_numeric($valor)); // true
var_dump(is_string($valor));  // true
var_dump(is_int($valor));     // false

is_numeric() comprueba si una cadena representa un número, pero no distingue por sí sola si es un entero o un decimal. Podemos utilizar filtros como FILTER_VALIDATE_INT, FILTER_VALIDATE_FLOAT y FILTER_VALIDATE_EMAIL.

Actividad

Identificar el valor recibido

Haz un formulario que reciba un valor y compruebe si representa un entero, un número decimal o una cadena no numérica.

Actividad

Tabla de multiplicar

Crea un formulario para introducir un número. Comprueba que se ha enviado y que contiene un valor numérico válido antes de mostrar su tabla de multiplicar.

Orientación para la solución
php
<?php
$numero = filter_input(INPUT_POST, 'numero', FILTER_VALIDATE_INT);
if ($numero === false || $numero === null) {
    echo 'Introduce un número entero válido.';
} else {
    for ($i = 1; $i <= 10; $i++) {
        echo "$numero × $i = " . ($numero * $i) . '<br>';
    }
}

El formulario debe utilizar method="POST" y un campo name="numero".

Actividad: ficha de datos personales ​

Actividad

Crear y procesar un formulario

Realiza un formulario que solicite:

  • Nombre, apellidos y dirección.
  • Fecha de nacimiento y edad.
  • Idiomas que habla, entre cuatro opciones (checkbox).
  • Género, con la opción de no informar (radio).
  • Correo electrónico (email).
  • Estudios: ESO, Bachillerato, Ciclo Formativo o Grado Universitario (select).

En una segunda página, muestra una ficha con los datos recibidos.

Posible solución: index.php
html
<!doctype html>
<html lang="es">
<head><meta charset="UTF-8"><title>Datos personales</title></head>
<body>
<form action="datos.php" method="POST">
    <fieldset>
        <legend>Datos personales</legend>
        <label>Nombre <input type="text" name="nombre"></label>
        <label>Apellidos <input type="text" name="apellido"></label>
        <label>Dirección <input type="text" name="direccion"></label>
        <label>Fecha de nacimiento <input type="date" name="fNac"></label>
        <label>Edad <input type="number" name="edad" min="0"></label>

        <p>Idiomas</p>
        <label><input type="checkbox" name="idiomas[]" value="castellano"> Castellano</label>
        <label><input type="checkbox" name="idiomas[]" value="rumano"> Rumano</label>
        <label><input type="checkbox" name="idiomas[]" value="ingles"> Inglés</label>
        <label><input type="checkbox" name="idiomas[]" value="frances"> Francés</label>

        <p>Género</p>
        <label><input type="radio" name="genero" value="masculino"> Masculino</label>
        <label><input type="radio" name="genero" value="femenino"> Femenino</label>
        <label><input type="radio" name="genero" value="no_aporta"> No quiero informar</label>

        <label>Correo electrónico <input type="email" name="email"></label>
        <label>Estudios
            <select name="estudios">
                <option value="eso">ESO</option>
                <option value="bach">Bachillerato</option>
                <option value="cicloFormativo">Ciclo Formativo</option>
                <option value="gradoUniversitario">Grado Universitario</option>
            </select>
        </label>
        <button type="submit">Enviar</button>
    </fieldset>
</form>
</body>
</html>
Posible solución: datos.php
php
<?php
function escapar(string $texto): string {
    return htmlspecialchars($texto, ENT_QUOTES, 'UTF-8');
}

$nombre = trim((string) (filter_input(INPUT_POST, 'nombre') ?? ''));
$apellidos = trim((string) (filter_input(INPUT_POST, 'apellido') ?? ''));
$direccion = trim((string) (filter_input(INPUT_POST, 'direccion') ?? ''));
$fecha = (string) (filter_input(INPUT_POST, 'fNac') ?? '');
$edad = filter_input(INPUT_POST, 'edad', FILTER_VALIDATE_INT);
$idiomas = filter_input(INPUT_POST, 'idiomas', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
$idiomas = is_array($idiomas) ? $idiomas : [];
$genero = (string) (filter_input(INPUT_POST, 'genero') ?? '');
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$estudios = (string) (filter_input(INPUT_POST, 'estudios') ?? '');
?>
<!doctype html>
<html lang="es">
<head><meta charset="UTF-8"><title>Ficha personal</title></head>
<body>
<h1>Datos personales</h1>
<p>Nombre: <?= escapar($nombre) ?></p>
<p>Apellidos: <?= escapar($apellidos) ?></p>
<p>Dirección: <?= escapar($direccion) ?></p>
<p>Fecha de nacimiento: <?= escapar($fecha) ?></p>
<p>Edad: <?= $edad === false || $edad === null ? 'No válida' : $edad ?></p>
<p>Idiomas: <?= escapar(implode(', ', array_map('strval', $idiomas))) ?></p>
<p>Género: <?= escapar($genero) ?></p>
<p>Correo: <?= $email === false || $email === null ? 'No válido' : escapar($email) ?></p>
<p>Estudios: <?= escapar($estudios) ?></p>
</body>
</html>

Esta solución ilustra la lectura y el escape de salida; en una aplicación real también se deben validar los valores permitidos de cada campo y comprobar los tipos de los datos recibidos.

Filtrado y seguridad: XSS ​

Si mostramos directamente en una página HTML el contenido enviado por un usuario, podemos introducir una vulnerabilidad XSS (Cross-Site Scripting): el navegador podría interpretar contenido no confiable como código ejecutable.

Ejemplo de salida insegura
php
<?php
$nombre = $_GET['nombre'] ?? '';
echo $nombre; // No usar con datos externos sin escapar
Salida segura en contexto HTML
php
<?php
$nombre = $_GET['nombre'] ?? '';
echo htmlspecialchars($nombre, ENT_QUOTES, 'UTF-8');
Validar no es lo mismo que escapar
  • Validar: comprobar que el dato cumple las reglas esperadas (por ejemplo, que una edad sea un entero).
  • Escapar la salida: convertir caracteres especiales para que el dato se muestre como texto en su contexto de destino. Para texto dentro de HTML, usamos htmlspecialchars().
  • Filtrar: aplicar una regla de validación o transformación con funciones como filter_var() y filter_input().

No debemos confiar en que un navegador bloquee los ataques. strip_tags() tampoco sustituye el escape correcto de salida.

filter_var() y filter_input() ​

php
<?php
$correo = 'alumno@example.com';
var_dump(filter_var($correo, FILTER_VALIDATE_EMAIL));

$edad = filter_input(INPUT_POST, 'edad', FILTER_VALIDATE_INT);
  • filter_var($valor, $filtro) aplica un filtro a un valor que ya tenemos.
  • filter_input(INPUT_POST, 'edad', $filtro) lee y filtra un dato de entrada.
  • Un filtro de validación suele devolver el valor validado, false si falla o null si falta el dato; conviene usar comparaciones estrictas.

Consulta la referencia de filtros de PHP.

Actividad

Filtrando valores

Crea un formulario que permita introducir diferentes valores. Comprueba cuáles son enteros válidos, números decimales o direcciones de correo electrónico. Muestra los valores recibidos de forma segura.

Ejercicios ​

Ejercicio 1: Página de producto de una tienda
Enunciado

Crea una página web que simule una tienda online.

  • Muestra un producto con su imagen y precio.
  • Incluye una caja de texto para escribir un comentario.
  • Al pulsar el botón Publicar, el comentario debe aparecer debajo de la imagen del producto.
  • Puedes usar la imagen:
Diagrama de xss_cascos.jpeg
Imagen generada con IA (OpenAI, ChatGPT).
PHPCódigo del ejercicio
ejercicio.php
Salida
Pulsa «Ejecutar» para ver el resultado.
© 2026 · DAWS · Desarrollo Web en Entorno Servidor