Menu

PHP filter_var(): validar email, int, URL y más

filter_var($value, FILTER_VALIDATE_EMAIL) devuelve el valor si es válido y false si no; FILTER_VALIDATE_INT, FILTER_VALIDATE_URL, FILTER_VALIDATE_BOOL y FILTER_VALIDATE_IP funcionan igual. Aprende las opciones (min_range, default), las flags, los filtros de saneamiento y la trampa de false frente a 0.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

filter_var($value, FILTER_VALIDATE_EMAIL) devuelve el valor cuando es una dirección de email válida y false cuando no lo es. Cambia el filtro para comprobar otros formatos: FILTER_VALIDATE_INT, FILTER_VALIDATE_FLOAT, FILTER_VALIDATE_URL, FILTER_VALIDATE_BOOL, FILTER_VALIDATE_IP. Compara siempre el resultado con === false.

Dos resultados sorprenden. ada@example se rechaza porque el dominio no tiene punto, y ' ada@example.com' se rechaza por el espacio inicial, así que aplica trim() a la entrada antes de validarla.

Validar un email de un formulario

La misma comprobación detrás de un formulario. Ejecútalo, escribe una dirección y pulsa Check; el bloque se ejecuta otra vez con tu entrada en $_POST.

FILTER_VALIDATE_EMAIL solo comprueba el formato. nobody@example.com pasa, y también pasaría una dirección con una errata en el dominio. Los caracteres no ASCII se rechazan: adä@example.com solo pasa con FILTER_FLAG_EMAIL_UNICODE, que los permite antes de la @, y un dominio como exämple.com falla incluso con la flag salvo que antes lo conviertas a su forma xn--. La única forma de saber si una dirección funciona es enviarle un enlace de confirmación.

Validar un entero con min_range y max_range

FILTER_VALIDATE_INT convierte una cadena válida en un int y rechaza todo lo demás. El array de opciones añade un rango y un valor por defecto:

Se aceptan los espacios alrededor y un + inicial, un cero inicial ('042') no, y el resultado para '42' es el entero 42, no la cadena. Fuera de rango da false; con una opción default obtienes el valor por defecto en lugar de false, algo práctico para cosas como ?page= (consulta GETy_GET y _POST). Añade FILTER_FLAG_ALLOW_HEX o FILTER_FLAG_ALLOW_OCTAL para aceptar 0x1A o 0755.

La trampa de 0 y false

Un '0' válido devuelve el entero 0, y 0 es falsy. Un if simple lo trata como un fallo:

Lo mismo se aplica a FILTER_VALIDATE_FLOAT ('0.0') y a FILTER_VALIDATE_BOOL, donde false es una respuesta válida. Para eso existe FILTER_NULL_ON_FAILURE.

Booleanos, floats, URLs y direcciones IP

FILTER_VALIDATE_BOOL es el nombre de PHP 8; FILTER_VALIDATE_BOOLEAN es el mismo filtro. Sin FILTER_NULL_ON_FAILURE, 'maybe' devolvería false, imposible de distinguir de 'off'.

Una URL válida no es un enlace seguro

FILTER_VALIDATE_URL comprueba que la cadena tenga forma de URL, con cualquier esquema. Eso incluye esquemas que nunca querrías en un href:

javascript://comment%0Aalert(1) pasa FILTER_VALIDATE_URL, y un navegador lo ejecuta como JavaScript cuando se hace clic en el enlace, porque %0A termina el //comment. Comprueba el esquema con parse_url() antes de imprimir la URL de un usuario en una página. También puedes exigir partes con FILTER_FLAG_PATH_REQUIRED y FILTER_FLAG_QUERY_REQUIRED.

Filtros de saneamiento

Los filtros de saneamiento eliminan caracteres en lugar de responder sí o no. Son útiles para normalizar la entrada, no para que sea segura al imprimirla:

Mira la primera línea: Order #12-345 (x2) se convierte en 12-3452, un número que nunca estuvo en la entrada, y la tercera línea es una dirección que nadie escribió. Si saneas, valida después el resultado. Para todo lo que imprimes en HTML, la herramienta adecuada es htmlspecialchars() en el momento de la salida (FILTER_SANITIZE_FULL_SPECIAL_CHARS hace el mismo escapado). FILTER_SANITIZE_STRING está obsoleto desde PHP 8.1; consulta htmlspecialchars para saber qué usar en su lugar.

Validar un formulario entero con filter_var_array

filter_var_array() aplica un filtro por clave y devuelve un array con todas las claves que pediste: el valor filtrado, false cuando falló la validación, o null cuando faltaba la clave.

role ha desaparecido: las claves que no listaste se descartan, lo que impide que un visitante añada role=admin a un formulario y que se guarde. country es null porque no se envió. En un servidor web, filter_input_array(INPUT_POST, $rules) hace lo mismo leyendo directamente de la petición.

Preguntas frecuentes

¿Cómo valido una dirección de email en PHP?

Usa filter_var($email, FILTER_VALIDATE_EMAIL), que devuelve la cadena del email si es válida y false si no: if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) { /* invalid */ }. Solo comprueba el formato; para saber si la dirección existe, envía un email de confirmación.

¿Cómo compruebo si una cadena es un entero en PHP?

filter_var($s, FILTER_VALIDATE_INT) devuelve el int para "42", "-7" y " 42 ", y false para "4.2", "42abc" o "042". Compara con !== false, porque un "0" válido devuelve 0, que es falsy.

¿Por qué filter_var devuelve false con 0?

No lo hace: filter_var('0', FILTER_VALIDATE_INT) devuelve el entero 0. El bug está en la comprobación, if (filter_var(...)), que trata 0 como false. Escribe if (filter_var($v, FILTER_VALIDATE_INT) !== false).

¿Qué sustituyó a FILTER_SANITIZE_STRING en PHP 8.1?

Nada directamente; quedó obsoleto porque su nombre prometía una seguridad que no daba. Valida la entrada que esperas, guárdala tal cual y escápala al imprimirla con htmlspecialchars(). Si necesitas quitar etiquetas, usa strip_tags().

¿Cuál es la diferencia entre filter_var y filter_input?

filter_var() filtra cualquier valor que le pases. filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT) lee directamente de la petición original, así que devuelve null cuando falta el parámetro e ignora cualquier cambio que tu código haya hecho en $_GET. Las dos aceptan los mismos filtros y opciones.

Ilustración de los lenguajes de programación de Coddy

Aprende a programar con Coddy

COMENZAR