flawopen.com/SQL Injection em PHP/mysqli vs PDO
MySQLi vs PDO: prepared statements seguros
Uma prepared statement mantém as instruções SQL fixas e envia os valores separadamente, como preencher campos identificados em um formulário. PDO e MySQLi fazem isso. A segurança vem do binding correto, não do nome da biblioteca.
A mesma consulta, preparada com qualquer API
$userId = $_GET['id']; $sql = "SELECT id, email FROM users WHERE id = " . $userId; // Both calls execute the already-built SQL string: $rows = $mysqli->query($sql); $rows = $pdo->query($sql);
// PDO $stmt = $pdo->prepare( "SELECT id, email FROM users WHERE id = :id" ); $stmt->execute(["id" => $userId]); // MySQLi $stmt = $mysqli->prepare( "SELECT id, email FROM users WHERE id = ?" ); $stmt->bind_param("i", $userId); $stmt->execute();
Portabilidade de banco é a principal diferença do PDO
PDO oferece uma interface comum para vários drivers; MySQLi é voltado a MySQL e MariaDB. PDO não torna SQL portável automaticamente: dialetos, drivers e recursos ainda variam.
PDO aceita placeholders nomeados como :id ou posicionais ?, conforme o driver; não misture os estilos na mesma instrução. MySQLi usa ? posicional. Ambos vinculam valores, mas não nomes de tabela/coluna, palavras-chave ou ordenação.
Drivers PDO podem usar prepared statements nativas ou emuladas. No MySQL, PDO::ATTR_EMULATE_PREPARES controla a emulação quando disponível; alguns drivers emulam ou recorrem a ela quando a preparação nativa não é possível. Siga a documentação do driver. Essa opção não protege SQL interpolado: mantenha o texto fixo e vincule valores em qualquer modo.
Regras que evitam SQL injection em ambas as bibliotecas
Use prepare() e vincule cada valor não confiável. Mantenha a sintaxe SQL fixa; selecione identificadores dinâmicos por um mapa estrito no servidor ou use variantes finitas de consulta. Prepared statements não autorizam acesso a registros: restrinja a consulta ao usuário autenticado quando necessário. Em LIKE, binding evita injeção de sintaxe, mas % e _ continuam curingas, a menos que sejam escapados para busca literal.
Escolhendo entre PDO e MySQLi
- ✓Escolha PDO quando precisar de uma API comum entre drivers; confirme dialeto e comportamento do driver na migração.
- ✓Escolha MySQLi para aplicações somente MySQL/MariaDB que precisam da API específica do MySQL.
- ✓Em ambas, procure interpolação, concatenação e identificadores dinâmicos; vincule valores e autorize registros separadamente.
Perguntas frequentes
Não. Ambos vinculam valores com segurança quando a consulta é preparada e os valores são vinculados. Nomes podem melhorar a leitura; não vinculam identificadores nem substituem autorização.
Não como regra universal. Suporte e fallback variam por driver. Consulte a documentação e os requisitos da aplicação. Em qualquer modo, mantenha a estrutura SQL fixa e passe valores como parâmetros.
Não. Parâmetros representam valores, não identificadores ou palavras-chave SQL. Mapeie escolhas do cliente a um conjunto finito de fragmentos confiáveis no servidor.
Referências
- Manual do PHP — prepared statements do PDO
- Manual do PHP — prepared statements do MySQLi
- Manual do PHP — PDO::setAttribute e prepared statements emulados
- FlawOpen — SQL Injection em PHP