W3docs

real_escape_string

Aprende a usar mysqli_real_escape_string() en PHP para escapar caracteres especiales en cadenas usadas en consultas SQL y prevenir inyecciones.

La función mysqli_real_escape_string() escapa los caracteres especiales de una cadena para que pueda colocarse de forma segura dentro de una consulta SQL. Esta página explica qué hace la función, su sintaxis y valor de retorno, el problema del conjunto de caracteres que puede romperla, la obsoleta mysql_real_escape_string() que reemplazó, y por qué las sentencias preparadas son la mejor opción hoy en día.

Qué hace mysqli_real_escape_string()

Cuando construyes una consulta SQL concatenando directamente la entrada del usuario en la cadena de consulta, un valor como O'Reilly cierra anticipadamente la cadena entre comillas y el resto se trata como SQL. Un atacante puede explotar esto para leer, modificar o eliminar datos — un ataque de inyección SQL.

mysqli_real_escape_string() evita esto añadiendo barras invertidas antes de los caracteres que tienen significado especial dentro de un literal de cadena MySQL: la comilla simple ', la comilla doble ", la barra invertida \, el byte NUL, el salto de línea \n, el retorno de carro \r y Ctrl+Z. Tras el escape, el valor es seguro para insertarlo entre comillas en una consulta.

Es "real" porque consulta el conjunto de caracteres de la conexión, por lo que escapa correctamente incluso para codificaciones multibyte — algo que la antigua addslashes() no puede hacer.

Sintaxis

mysqli_real_escape_string(mysqli $connection, string $string): string
ParámetroDescripción
$connectionUn enlace devuelto por mysqli_connect(). La función lo necesita para conocer el conjunto de caracteres de la conexión.
$stringLa cadena a escapar.

Devuelve la cadena escapada. Ten en cuenta que no añade las comillas circundantes — tú mismo debes escribir '$escaped' en la consulta.

En estilo orientado a objetos, llámala como método: $mysqli->real_escape_string($string).

Cómo usarla

<?php
$con = mysqli_connect('localhost', 'username', 'password', 'database');

if (!$con) {
    exit('Could not connect: ' . mysqli_error($con));
}

// Set charset to prevent multi-byte character vulnerabilities
mysqli_set_charset($con, 'utf8mb4');

$name = "John O'Reilly";
$name = mysqli_real_escape_string($con, $name);

$sql = "INSERT INTO customers (name) VALUES ('$name')";

if (!mysqli_query($con, $sql)) {
    exit('Error: ' . mysqli_error($con));
}

echo '1 record added';

mysqli_close($con);
?>

Aquí nos conectamos con mysqli_connect(), definimos $name con una comilla simple y la escapamos. El valor escapado John O\'Reilly encaja de forma segura en el marcador de posición '$name', por lo que el INSERT se ejecuta sin error de sintaxis y sin abrir una vulnerabilidad de inyección. Consulta Insertar datos en MySQL para ver el flujo completo de inserción.

Establecer el conjunto de caracteres primero

mysqli_real_escape_string() solo escapa correctamente si la conexión conoce su conjunto de caracteres. Siempre llama a mysqli_set_charset() justo después de conectarte:

mysqli_set_charset($con, 'utf8mb4');

Omitir esto en ciertas codificaciones (especialmente GBK) deja un vector de inyección multibyte donde la barra invertida de escape es "consumida" por una secuencia multibyte. Establecer el conjunto de caracteres en la conexión — no solo en la consulta — cierra esa vulnerabilidad.

Lo que no protege

El escape hace que un valor sea seguro dentro de un literal de cadena entre comillas. No hace que los valores sean seguros en lugares donde no se pueden usar comillas — nombres de tablas y columnas, números en LIMIT, o palabras clave. Nunca escapes un identificador y lo insertes en una consulta; valídalo contra una lista de permitidos en su lugar.

// WRONG — escaping does nothing useful for an identifier
$column = mysqli_real_escape_string($con, $_GET['sort']);
$sql = "SELECT * FROM users ORDER BY $column"; // still injectable

// RIGHT — allow-list
$allowed = ['name', 'email', 'created_at'];
$column  = in_array($_GET['sort'], $allowed, true) ? $_GET['sort'] : 'name';

mysql_real_escape_string() vs mysqli_real_escape_string()

La antigua mysql_real_escape_string() (sin la i) pertenecía a la extensión original mysql_*, que fue eliminada en PHP 7. Usa la versión mysqli_* — o PDO — en cualquier PHP moderno. Si la llamas sin una conexión activa, abre silenciosamente una conexión por defecto y emite una advertencia, lo cual es otra razón por la que fue retirada.

Preferir sentencias preparadas

El escape funciona, pero depende de que nunca olvides escapar un solo valor. Las sentencias preparadas son más seguras porque la plantilla de consulta y los datos viajan por separado, por lo que la entrada del usuario nunca puede cambiar la estructura de la consulta:

<?php
$con = mysqli_connect('localhost', 'username', 'password', 'database');
mysqli_set_charset($con, 'utf8mb4');

$stmt = mysqli_prepare($con, 'INSERT INTO customers (name) VALUES (?)');
mysqli_stmt_bind_param($stmt, 's', $name);

$name = "John O'Reilly"; // no manual escaping needed
mysqli_stmt_execute($stmt);

echo '1 record added';
mysqli_close($con);
?>

Usa mysqli_real_escape_string() cuando realmente tengas que construir SQL dinámico a mano; utiliza mysqli_prepare() en el resto de los casos. Para una descripción general de la extensión, consulta PHP MySQLi.

Conclusión

mysqli_real_escape_string() escapa los caracteres especiales que de otro modo romperían — o serían explotados en — un literal de cadena SQL. Establece el conjunto de caracteres de la conexión primero, recuerda que no hace nada para los identificadores, y prefiere las sentencias preparadas siempre que puedas.

Práctica

Práctica
What does the PHP function mysql_real_escape_string function do?
What does the PHP function mysql_real_escape_string function do?
Was this page helpful?