As regras para adicionar uma variável PHP dentro de qualquer instrução MySQL são claras e simples:
- Qualquer variável que represente um literal de dados SQL , (ou, para simplificar - uma string SQL ou um número) DEVE ser adicionado por meio de uma instrução preparada. Sem exceções.
- Qualquer outra parte da consulta, como uma palavra-chave SQL, uma tabela ou um nome de campo ou um operador, deve ser filtrada por uma lista branca .
Portanto, como seu exemplo envolve apenas literais de dados, todas as variáveis devem ser adicionadas por meio de espaços reservados (também chamados de parâmetros). Para fazer isso:
- Em sua instrução SQL, substitua todas as variáveis por espaços reservados
- preparar a consulta resultante
- vincular variáveis para espaços reservados
- executar a consulta
E aqui está como fazer isso com todos os drivers de banco de dados PHP populares:
Adicionando literais de dados usando mysql ext
Tal driver não existe .
Adicionando literais de dados 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();
O código é um pouco complicado, mas a explicação detalhada de todos esses operadores pode ser encontrada no meu artigo, Como executar um INSERIR consulta usando Mysqli , bem como uma solução que facilita drasticamente o processo.
Para uma consulta SELECT, você precisará adicionar apenas uma chamada para
get_result()
método para obter um mysqli_result
familiar a partir do qual você pode buscar os dados da maneira usual:$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 (...)
Adicionando literais de dados 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]);
No PDO, podemos combinar as partes bind e execute, o que é muito conveniente. O PDO também suporta espaços reservados nomeados que alguns consideram extremamente convenientes.
Adicionar palavras-chave ou identificadores
Às vezes temos que adicionar uma variável que representa outra parte de uma consulta, como uma palavra-chave ou um identificador (um banco de dados, uma tabela ou um nome de campo). É um caso raro, mas é melhor estar preparado.
Nesse caso, sua variável deve ser verificada em relação a uma lista de valores explicitamente escrito em seu roteiro. Isso é explicado em meu outro artigo, Adicionando um nome de campo na cláusula ORDER BY com base na escolha do usuário :
Infelizmente, o PDO não tem espaço reservado para identificadores (nomes de tabelas e campos), portanto, um desenvolvedor deve filtrá-los manualmente. Esse filtro geralmente é chamado de "lista branca" (onde apenas listamos valores permitidos) em oposição a uma "lista negra" onde listamos valores não permitidos.
Portanto, temos que listar explicitamente todas as variantes possíveis no código PHP e depois escolher entre elas.
Aqui está um exemplo:
$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");
}
Exatamente a mesma abordagem deve ser usada para a direção,
$direction = $_GET['direction'] ?: "ASC";
$allowed = ["ASC","DESC"];
$key = array_search($direction, $allowed, true);
if ($key === false) {
throw new InvalidArgumentException("Invalid ORDER BY direction");
}
Após esse código, tanto
$direction
e $orderby
variáveis podem ser colocadas com segurança na consulta SQL, pois são iguais a uma das variantes permitidas ou haverá um erro. A última coisa a mencionar sobre os identificadores, eles também devem ser formatados de acordo com a sintaxe específica do banco de dados. Para MySQL deve ser
backtick
caracteres ao redor do identificador. Portanto, a string de consulta final para nosso pedido por exemplo seria $query = "SELECT * FROM `table` ORDER BY `$orderby` $direction";