Operações com bancos de dados PDO

Você já aprendeu os comandos do MySQL, mas o verdadeiro objetivo é operar o banco de dados a partir do PHP. O PDO (PHP Data Objects) é a camada de abstração de banco de dados padrão recomendada pelo PHP — um único conjunto de código funciona com 12 tipos de bancos de dados. Lembre-se: aprenda PDO, ignore o MySQLi.

1. Por que o PDO?

PDO MySQLi
Bancos de dados compatíveis 12 (MySQL/PostgreSQL/SQLite...) Apenas MySQL
Parâmetros nomeados :name ❌ apenas ?
Recuperar matrizes associativas PDO::FETCH_ASSOC
Buscar objetos PDO::FETCH_OBJ ❌ (requer configuração adicional)
Modo de exceção ✅ Configurável ✅ Configurável
Modernidade 🏆 Padrão da comunidade Tradição

2. Conexão PDO

PHP
<?php
$host = 'localhost';
$dbname = 'myblog';
$username = 'root';
$password = '';
$charset = 'utf8mb4';

$dsn = "mysql:host={$host};dbname={$dbname};charset={$charset}";

try {
    $pdo = new PDO($dsn, $username, $password, [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => false,
    ]);
    echo "✅ Database connected successfully!<br>";
} catch (PDOException $e) {
    die("❌ Connection failed: " . $e->getMessage());
}
?>
Opção de conexão Significado Por que
ERRMODE_EXCEPTION Lançar exceções em caso de erros Sem falhas silenciosas
FETCH_ASSOC Padrão para matrizes associativas Formato mais utilizado
EMULATE_PREPARES => false Use instruções preparadas de verdade Segurança de verdade
💡 Dica: Essas três opções do PDO constituem a configuração padrão — inclua-as sempre ao criar uma conexão PDO. EMULATE_PREPARES => false garante que sejam utilizadas as instruções preparadas nativas do MySQL, em vez das emuladas pelo PDO.


3. query() — Execução de consultas SELECT

PHP
<?php
// Simple query
$stmt = $pdo->query("SELECT * FROM users");
$users = $stmt->fetchAll();

// Iterate results
foreach ($users as $user) {
    echo "ID: {$user['id']}, Username: {$user['username']}<br>";
}

// Fetch a single row
$stmt = $pdo->query("SELECT * FROM users WHERE id = 1");
$user = $stmt->fetch();

echo $user['username'];  // John
?>

(1) Modos de busca

PHP
<?php
$stmt = $pdo->query("SELECT id, username FROM users");

// Associative array (default)
$row = $stmt->fetch(PDO::FETCH_ASSOC);
echo $row['username'];

// Numeric index
$row = $stmt->fetch(PDO::FETCH_NUM);
echo $row[1];

// Object
$row = $stmt->fetch(PDO::FETCH_OBJ);
echo $row->username;

// Fetch a single column
$usernames = $stmt->fetchAll(PDO::FETCH_COLUMN, 1);
print_r($usernames);  // ['John', 'Jane', ...]
?>

4. Instruções preparadas (Fundamental!)

As instruções preparadas são a chave para prevenir a injeção de SQL:

▶ Exemplo: Consulta segura do usuário

PHP
<?php
// ❌ Dangerous: direct SQL concatenation (SQL injection vulnerability)
// $stmt = $pdo->query("SELECT * FROM users WHERE username = '$input'");

// ✅ Safe: prepared statement
$username = $_GET['username'] ?? '';

$sql = "SELECT * FROM users WHERE username = :username";
$stmt = $pdo->prepare($sql);
$stmt->execute(['username' => $username]);
$user = $stmt->fetch();

if ($user) {
    echo "Found user: {$user['username']}";
} else {
    echo "User not found";
}
?>
▶ Experimente

(1) INSERIR

PHP
<?php
$sql = "INSERT INTO users (username, email, password, age) 
        VALUES (:username, :email, :password, :age)";

$stmt = $pdo->prepare($sql);
$stmt->execute([
    'username' => 'Alex',
    'email'    => 'alex@example.com',
    'password' => password_hash('123456', PASSWORD_DEFAULT),
    'age'      => 24,
]);

$newId = $pdo->lastInsertId();
echo "New user ID: {$newId}";
?>

(2) ATUALIZAÇÃO

PHP
<?php
$sql = "UPDATE users SET age = :age WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute(['age' => 27, 'id' => 1]);

echo "Affected {$stmt->rowCount()} row(s)";
?>

(3) EXCLUIR

PHP
<?php
$sql = "DELETE FROM users WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute(['id' => 5]);

echo "Deleted {$stmt->rowCount()} row(s)";
?>

5. CRUD completo na prática

▶ Exemplo: Página de gerenciamento de usuários

PHP
<?php
// Database connection (same as above, omitted for brevity)
$pdo = new PDO($dsn, $username, $password, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);

// Handle form submissions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $action = $_POST['action'] ?? '';
    
    if ($action === 'add') {
        $stmt = $pdo->prepare(
            "INSERT INTO users (username, email, password, age) 
             VALUES (:username, :email, :password, :age)"
        );
        $stmt->execute([
            'username' => $_POST['username'],
            'email'    => $_POST['email'],
            'password' => password_hash($_POST['password'], PASSWORD_DEFAULT),
            'age'      => (int)$_POST['age'],
        ]);
        echo "<p style='color:green'>User added successfully!</p>";
    } elseif ($action === 'delete') {
        $stmt = $pdo->prepare("DELETE FROM users WHERE id = :id");
        $stmt->execute(['id' => (int)$_POST['id']]);
        echo "<p style='color:green'>User deleted!</p>";
    }
}

// Query all users
$users = $pdo->query("SELECT * FROM users ORDER BY id DESC")->fetchAll();
?>

<h2>User Management</h2>

<table border="1" cellpadding="8">
    <tr><th>ID</th><th>Username</th><th>Email</th><th>Age</th><th>Registered</th><th>Actions</th></tr>
    <?php foreach ($users as $u): ?>
    <tr>
        <td><?= $u['id'] ?></td>
        <td><?= htmlspecialchars($u['username']) ?></td>
        <td><?= htmlspecialchars($u['email']) ?></td>
        <td><?= $u['age'] ?></td>
        <td><?= $u['created_at'] ?></td>
        <td>
            <form method="POST" style="display:inline">
                <input type="hidden" name="action" value="delete">
                <input type="hidden" name="id" value="<?= $u['id'] ?>">
                <button type="submit" onclick="return confirm('Confirm deletion?')">Delete</button>
            </form>
        </td>
    </tr>
    <?php endforeach; ?>
</table>

<h3>Add User</h3>
<form method="POST">
    <input type="hidden" name="action" value="add">
    <input type="text" name="username" placeholder="Username" required>
    <input type="email" name="email" placeholder="Email" required>
    <input type="password" name="password" placeholder="Password" required>
    <input type="number" name="age" placeholder="Age">
    <button type="submit">Add</button>
</form>
▶ Experimente

❓ Perguntas Frequentes

P: PDO ou MySQLi — qual devo escolher? R: PDO. Ele oferece suporte a 12 tipos de bancos de dados (é possível alternar entre bancos de dados sem precisar reescrever o código), possui uma sintaxe mais clara para instruções preparadas (:name parâmetros nomeados) e é o padrão aceito pela comunidade PHP. O MySQLi é adequado apenas para a manutenção de projetos legados.

P: Por que as instruções preparadas evitam a injeção de SQL? R: As instruções preparadas separam a estrutura do SQL dos dados — o SQL é enviado ao MySQL e compilado em um plano de execução primeiro, e os dados são passados como parâmetros posteriormente. O banco de dados sabe exatamente o que é um comando e o que são dados, por isso nunca trata os dados como código executável.

P: Qual é a diferença entre fetch() e fetchAll()? R: fetch() recupera uma linha por vez (cada chamada retorna uma linha) — ideal para conjuntos de resultados grandes. fetchAll() recupera tudo de uma só vez em um array — mais simples, mas pode consumir muita memória em conjuntos de dados grandes.

📖 Resumo

📝 Exercícios

  1. Use o PDO para se conectar ao banco de dados do myblog, consultar todos os dados da tabela users e exibi-los em uma tabela.
  2. Crie uma página de cadastro com um formulário para nome de usuário/e-mail/senha. Use instruções preparadas do PDO para inserir o novo usuário (não se esqueça de password_hash).
  3. Adicione um botão “Excluir” a cada linha da tabela do exercício 1. Ao clicar nele, o registro do usuário correspondente deve ser excluído.
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%