Da trilha de PHP Este conceito ainda não saiu como card do dia. ir para o card de hoje

PHP Banco de dados Avançado

PDO

O PDO (PHP Data Objects) é uma camada de abstração para acesso a bancos de dados em PHP. Ele fornece uma interface única para trabalhar com diferentes SGBDs (MySQL, PostgreSQL, SQLite, etc.), além de oferecer recursos avançados como prepared statements, transações e fetch modes flexíveis.

Neste card, focamos em um nível avançado: conexão segura, uso correto de prepared statements para evitar SQL injection, exploração dos fetch modes para moldar os resultados e controle transacional para garantir atomicidade.

O PDO é orientado a objetos e lança exceções em caso de erro (quando configurado). Isso permite um tratamento de erros mais limpo e robusto. Com ele, você escreve menos código específico de banco e ganha portabilidade.

Vamos ver um exemplo completo que cria uma tabela, insere dados, consulta com prepared statements e usa transação para uma operação atômica.

Pontos-chave

  • A conexão PDO usa DSN (Data Source Name) e opções como PDO::ATTR_ERRMODE para exceções.
  • Prepared statements separam a consulta dos dados, prevenindo SQL injection e melhorando performance.
  • Fetch modes como PDO::FETCH_ASSOC, PDO::FETCH_OBJ e PDO::FETCH_CLASS moldam o retorno.
  • Transações com beginTransaction, commit e rollBack garantem atomicidade em múltiplas operações.
  • Sempre capture PDOException para tratar falhas de conexão ou execução.
pdo_avancado.php
<?php
// Conexão com SQLite em memória (para exemplo executável sem servidor)
$pdo = new PDO('sqlite::memory:');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

// Cria tabela
$pdo->exec('CREATE TABLE usuarios (id INTEGER PRIMARY KEY, nome TEXT, email TEXT)');

// Inicia transação para inserir múltiplos registros atomicamente
$pdo->beginTransaction();
try {
    $stmt = $pdo->prepare('INSERT INTO usuarios (nome, email) VALUES (:nome, :email)');
    $stmt->execute([':nome' => 'Ana', ':email' => 'ana@exemplo.com']);
    $stmt->execute([':nome' => 'Bruno', ':email' => 'bruno@exemplo.com']);
    $pdo->commit();
    echo "Inserções commitadas.\n";
} catch (PDOException $e) {
    $pdo->rollBack();
    echo "Erro: " . $e->getMessage() . "\n";
}

// Consulta com prepared statement e fetch mode específico
$stmt = $pdo->prepare('SELECT id, nome, email FROM usuarios WHERE nome = :nome');
$stmt->execute([':nome' => 'Ana']);
$usuario = $stmt->fetch(PDO::FETCH_OBJ); // Retorna objeto
if ($usuario) {
    echo "Usuário: {$usuario->nome} ({$usuario->email})\n";
}

// Lista todos como array associativo (padrão definido)
$stmt = $pdo->query('SELECT * FROM usuarios');
$todos = $stmt->fetchAll();
foreach ($todos as $u) {
    echo "ID {$u['id']}: {$u['nome']}\n";
}

Exercícios

  1. 1
    Fácil

    Conexão e consulta simples com PDO

    Crie um script PHP que se conecte a um banco SQLite em memória, crie uma tabela produtos com colunas id (inteiro, chave primária) e nome (texto), insira dois produtos e liste todos os produtos usando fetchAll com o modo padrão PDO::FETCH_ASSOC.

    Resolver
  2. 2
    Médio

    Transação com rollback

    Crie um script que gerencie uma conta bancária simples. Crie uma tabela contas com id e saldo. Insira uma conta com saldo 100. Tente transferir 150 para outra conta (que não existe), mas dentro de uma transação que deve ser revertida (rollback) se o saldo for insuficiente. Exiba o saldo final da conta original.

    Resolver
  3. 3
    Desafio

    Relatório com fetch modes e transação

    Crie um script que gerencie pedidos. Crie tabelas clientes (id, nome) e pedidos (id, cliente_id, valor). Insira 3 clientes e vários pedidos. Usando uma transação, insira um novo pedido para um cliente existente. Em seguida, gere um relatório que liste cada cliente e o total de seus pedidos, usando PDO::FETCH_GROUP e PDO::FETCH_ASSOC para agrupar os resultados. Exiba o total geral de pedidos.

    Resolver

Continue estudando