Las reglas para agregar una variable de PHP dentro de cualquier declaración de MySQL son claras y simples:
- Cualquier variable que represente un literal de datos SQL , (o, para decirlo simplemente, una cadena SQL o un número) DEBE agregarse a través de una declaración preparada. Sin excepciones.
- Cualquier otra parte de la consulta, como una palabra clave de SQL, una tabla o un nombre de campo, o un operador, debe filtrarse a través de una lista blanca. .
Entonces, como su ejemplo solo involucra literales de datos, entonces todas las variables deben agregarse a través de marcadores de posición (también llamados parámetros). Para hacerlo:
- En su declaración SQL, reemplace todas las variables con marcadores de posición
- preparar la consulta resultante
- enlazar variables a marcadores de posición
- ejecutar la consulta
Y aquí está cómo hacerlo con todos los controladores de bases de datos PHP populares:
Agregar literales de datos usando mysql ext
Tal controlador no existe .
Agregar literales de datos usando mysqli
$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description)
VALUES(?, ?, 'whatever')";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("ss", $type, $reporter);
$stmt->execute();
El código es un poco complicado, pero la explicación detallada de todos estos operadores se puede encontrar en mi artículo, Cómo ejecutar un INSERTAR consulta usando Mysqli , así como una solución que facilita drásticamente el proceso.
Para una consulta SELECT, deberá agregar solo una llamada a get_result()
método para obtener un mysqli_result
familiar desde donde puede obtener los datos de la forma habitual:
$reporter = "John O'Hara";
$stmt = $mysqli->prepare("SELECT * FROM users WHERE name=?");
$stmt->bind_param("s", $reporter);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc(); // or while (...)
Agregar literales de datos usando PDO
$type = 'testing';
$reporter = "John O'Hara";
$query = "INSERT INTO contents (type, reporter, description)
VALUES(?, ?, 'whatever')";
$stmt = $pdo->prepare($query);
$stmt->execute([$type, $reporter]);
En PDO, podemos tener las partes enlazar y ejecutar combinadas, lo cual es muy conveniente. PDO también admite marcadores de posición con nombre que algunos encuentran extremadamente convenientes.
Agregar palabras clave o identificadores
A veces tenemos que agregar una variable que represente otra parte de una consulta, como una palabra clave o un identificador (una base de datos, una tabla o un nombre de campo). Es un caso raro pero es mejor estar preparado.
En este caso, su variable debe compararse con una lista de valores explícitamente escrito en su guión. Esto se explica en mi otro artículo, Agregar un nombre de campo en la cláusula ORDER BY según la elección del usuario :
Desafortunadamente, PDO no tiene un marcador de posición para los identificadores (nombres de tablas y campos), por lo tanto, un desarrollador debe filtrarlos manualmente. Dicho filtro a menudo se denomina "lista blanca" (donde solo enumeramos los valores permitidos) en lugar de una "lista negra" donde enumeramos los valores no permitidos.
Así que tenemos que enumerar explícitamente todas las variantes posibles en el código PHP y luego elegir entre ellas.
Aquí hay un ejemplo:
$orderby = $_GET['orderby'] ?: "name"; // set the default value
$allowed = ["name","price","qty"]; // the white list of allowed field names
$key = array_search($orderby, $allowed, true); // see if we have such a name
if ($key === false) {
throw new InvalidArgumentException("Invalid field name");
}
Se debe usar exactamente el mismo enfoque para la dirección,
$direction = $_GET['direction'] ?: "ASC";
$allowed = ["ASC","DESC"];
$key = array_search($direction, $allowed, true);
if ($key === false) {
throw new InvalidArgumentException("Invalid ORDER BY direction");
}
Después de dicho código, ambos $direction
y $orderby
las variables se pueden colocar de forma segura en la consulta SQL, ya que son iguales a una de las variantes permitidas o se generará un error.
Lo último que hay que mencionar sobre los identificadores es que también deben formatearse de acuerdo con la sintaxis de la base de datos en particular. Para MySQL debería ser backtick
caracteres alrededor del identificador. Entonces, la cadena de consulta final para nuestro pedido por ejemplo sería
$query = "SELECT * FROM `table` ORDER BY `$orderby` $direction";