filter_var() y filter_input() en PHP: validar y sanitizar datos de entrada

Las funciones filter_var() y filter_input() son la forma nativa de PHP para validar y sanitizar datos. Ofrecen filtros predefinidos para los tipos de datos más comunes: emails, URLs, enteros, floats, IPs y booleanos. Este artículo muestra cuándo usarlas, cuándo no son suficientes y el antipatrón más frecuente.

filter_var() para validación

<?php
// Validar email
$email = '[email protected]';
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo "Email válidon";
}

// Validar URL
$url = 'https://www.php.net/manual/es/';
if (filter_var($url, FILTER_VALIDATE_URL)) {
    echo "URL válidan";
}

// Validar entero con rango
$edad = '25';
$edadValida = filter_var($edad, FILTER_VALIDATE_INT, [
    'options' => ['min_range' => 0, 'max_range' => 150],
]);
var_dump($edadValida); // int(25) — convierte a int si es válido, false si no

// Validar IP (v4 e v6)
var_dump(filter_var('192.168.1.1', FILTER_VALIDATE_IP));       // string
var_dump(filter_var('::1', FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)); // string

// Validar float
$precio = '29,99'; // coma como separador decimal
var_dump(filter_var($precio, FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND)); // false
var_dump(filter_var('29.99', FILTER_VALIDATE_FLOAT)); // float(29.99)
?>

filter_input(): leer y validar desde superglobales

<?php
// Leer y validar en una sola llamada desde $_GET, $_POST, $_COOKIE, $_SERVER
$pagina = filter_input(INPUT_GET, 'pagina', FILTER_VALIDATE_INT, [
    'options' => ['default' => 1, 'min_range' => 1],
]);
// Si 'pagina' no existe o no es entero positivo, devuelve 1 (default)

$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
// null si la clave no existe, false si no es email válido

$busqueda = filter_input(INPUT_GET, 'q', FILTER_DEFAULT);
// El valor crudo, sin sanitizar (evita FILTER_SANITIZE_STRING)
?>

Sanitización: qué filtros usar

<?php
// FILTER_SANITIZE_EMAIL: elimina caracteres no válidos en emails
// (no valida, solo limpia)
$emailSucio = 'usuario [at] ejemplo .com';
$emailLimpio = filter_var($emailSucio, FILTER_SANITIZE_EMAIL);
echo $emailLimpio; // [email protected] — pero ¡no está garantizado que sea válido!

// FILTER_SANITIZE_NUMBER_INT: deja solo dígitos, + y -
$numero = filter_var('$1.234,56', FILTER_SANITIZE_NUMBER_INT);
echo $numero; // 123456 (elimina $, puntos y comas)

// FILTER_SANITIZE_URL: elimina caracteres no permitidos en URLs
$urlSucia = 'https://ejemplo.com/ruta con espacios';
echo filter_var($urlSucia, FILTER_SANITIZE_URL);
// https://ejemplo.com/rutaconspacios — cuidado, no es lo que esperas
?>

El antipatrón de FILTER_SANITIZE_STRING

<?php
// MAL: FILTER_SANITIZE_STRING fue deprecado en PHP 8.1
// Eliminaba etiquetas HTML y entidades, pero de forma inconsistente
// $nombre = filter_var($_POST['nombre'], FILTER_SANITIZE_STRING); // NO USAR

// BIEN: usar htmlspecialchars() para escapar HTML al mostrar
$nombre = $_POST['nombre'] ?? '';
$nombreSeguro = htmlspecialchars($nombre, ENT_QUOTES | ENT_HTML5, 'UTF-8');
echo $nombreSeguro; // los caracteres < > " ' & quedan escapados

// Para escapar en contextos distintos (URL, JS, SQL), usar la función apropiada
$url = urlencode($nombre);      // para parámetros GET
// Para SQL: usar prepared statements, no sanitización de strings
?>

Ejemplo real: procesar formulario de contacto

<?php
function procesarFormularioContacto(array $post): array
{
    $errores = [];
    $datos   = [];

    // Nombre: string limpio, no vacío
    $nombre = trim($post['nombre'] ?? '');
    if (strlen($nombre) < 2 || strlen($nombre) > 100) {
        $errores['nombre'] = 'El nombre debe tener entre 2 y 100 caracteres';
    } else {
        $datos['nombre'] = $nombre;
    }

    // Email: validación estricta
    $email = filter_var(trim($post['email'] ?? ''), FILTER_VALIDATE_EMAIL);
    if ($email === false) {
        $errores['email'] = 'Email no válido';
    } else {
        $datos['email'] = $email;
    }

    // Edad: entero en rango
    $edad = filter_var($post['edad'] ?? '', FILTER_VALIDATE_INT, [
        'options' => ['min_range' => 18, 'max_range' => 120],
    ]);
    if ($edad === false) {
        $errores['edad'] = 'Debes tener entre 18 y 120 años';
    } else {
        $datos['edad'] = $edad;
    }

    return ['errores' => $errores, 'datos' => $datos];
}
?>

La documentación oficial de filter_var() y la lista completa de filtros disponibles muestran todas las opciones de cada filtro, las flags aplicables y el comportamiento con valores null o tipos inesperados.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP