DEV Community

Léo Herte de Moraes
Léo Herte de Moraes

Posted on

Bancos de Dados: MySQL PDO

Extensão PDO

A PDO é uma biblioteca para abstração de conexões a bancos de dados — embutida no PHP desde a versão 5.1.0 — que fornece uma interface comum para conversar com vários bancos de dados diferentes. Por exemplo, você pode usar basicamente o mesmo código para fazer a interface com o MySQL ou SQLite:

// PDO + MySQL
$pdo = new PDO('mysql:host=example.com;dbname=database', 'user', 'password');
$statement = $pdo->query("SELECT some\_field FROM some\_table");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['some_field']);

// PDO + SQLite
$pdo = new PDO('sqlite:/path/db/foo.sqlite');
$statement = $pdo->query("SELECT some\_field FROM some\_table");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['some_field']);
Enter fullscreen mode Exit fullscreen mode

A PDO não irá traduzir suas consultas SQL ou emular funcionalidades que não existem; ela é feita puramente para conectar múltiplos tipos de bancos de dados com a mesma API.

Mais importante, a PDO permite que você injete de forma segura entradas externas (e.g IDs) em suas consultas SQL sem se preocupar com ataques de SQL injection. Isso é possível usando instruções PDO (PDO statements) e parâmetros restritos (bound parameters).

Vamos assumir que um script PHP recebe um ID numérico como parâmetro de uma consulta. Este ID deve ser usado para buscar um registro de um usuário no banco de dados. Essa é a forma errada de fazer isso:

$pdo = new PDO('sqlite:/path/db/users.db');
$pdo->query("SELECT name FROM users WHERE id = " . $_GET['id']); // <-- NÃO!
Enter fullscreen mode Exit fullscreen mode

Esse código é péssimo. Você está inserindo um parâmetro bruto na sua consulta SQL. Isso fará você ser hackeado num piscar de olhos, usando uma prática chamada SQL Injection. Apenas imagine se um hacker passar como parâmetro um id inventivo chamando uma URL como http://domain.com/?id=1%3BDELETE+FROM+users. Isso irá definir a variável $_GET['id'] como id=1;DELETE FROM users, o que irá excluir todos os seus usuários. Em vez disso, você deveria higienizar (sanitize) a entrada do ID usando parâmetros restritos da PDO.

$pdo = new PDO('sqlite:/path/db/users.db');
$stmt = $pdo->prepare('SELECT name FROM users WHERE id = :id');
$stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT); //<-- Higienizado automaticamente pela PDO
$stmt->execute();
Enter fullscreen mode Exit fullscreen mode

Esse é o código correto. Ele usa um parâmetro restrito em uma instrução PDO. Assim a entrada externa do ID é escapada antes de ser introduzida no banco de dados, prevenindo contra potenciais ataques de SQL injection.

Leia mais sobre a PDO

Você também deve estar ciente de que usam recursos do servidor e não é raro ter esses recursos esgotados se essas conexões não forem implicitamente fechadas, entretanto isso é mais comum em outras linguagens. Com PDO você pode implicitamente fechar as conexões pela destruição dos objetos garantindo que todas as referências a ele forem excluídas, ex. atribuindo NULL a elas. Se você não fizer isso explicitamente o PHP irá fechar todas as conexões quando seu script terminar - a não ser é claro que você esteja usando conexões persistentes.

Leia mais sobre conexões PDO

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay