Doctrine DBAL para PHP: guia completo com exemplos práticos
1. O que é e para que serve
Doctrine DBAL (Database Abstraction Layer) é uma biblioteca poderosa para PHP que fornece uma interface unificada para trabalhar com diferentes bancos de dados relacionais. Ela faz parte do ecossistema Doctrine, mas pode ser usada como um componente independente. O principal objetivo do DBAL é abstrair o desenvolvedor das particularidades de cada SGBD (MySQL, PostgreSQL, SQLite, Oracle, SQL Server, entre outros), permitindo escrever código portável.
Para que serve o Doctrine DBAL? Primeiro, ele simplifica bastante as operações comuns: conectar ao banco, executar consultas e gerenciar transações. Segundo, oferece segurança através de prepared statements e escape automático de parâmetros, protegendo contra injeção de SQL. Terceiro, o DBAL disponibiliza um Query Builder prático para construir consultas complexas sem escrever SQL puro. Diferente de um ORM completo (Object-Relational Mapper), o DBAL não exige mapeamento de objetos e entidades, sendo a escolha ideal para projetos que precisam de controle direto sobre o SQL, mas com mais praticidade.
A biblioteca é ativamente mantida, possui documentação excelente e é amplamente usada em desenvolvimento profissional. Ela é a base do Doctrine ORM e de vários frameworks PHP populares (Symfony, Laravel — através de integrações).
2. Instalação
A instalação do Doctrine DBAL é feita via Composer, o gerenciador de pacotes padrão do PHP. Execute no terminal, na raiz do seu projeto:
composer require doctrine/dbal
Após a instalação, a pasta vendor/ e o arquivo composer.json serão criados com a dependência adicionada. Para usar um SGBD específico, pode ser necessário instalar o driver PDO correspondente (por exemplo, ext-pdo_mysql para MySQL).
3. Primeiros passos — exemplo mínimo funcional
Crie um arquivo teste.php e inclua o autoload do Composer. Exemplo de conexão com SQLite (banco embutido, não precisa de servidor):
<?php
require_once 'vendor/autoload.php';
use Doctrine\DBAL\DriverManager;
// Parâmetros de conexão
$connectionParams = [
'dbname' => 'teste.db',
'driver' => 'pdo_sqlite',
];
// Cria a conexão
$conn = DriverManager::getConnection($connectionParams);
// Cria a tabela
$conn->executeStatement('CREATE TABLE IF NOT EXISTS usuarios (id INTEGER PRIMARY KEY AUTOINCREMENT, nome TEXT, email TEXT)');
// Insere dados
$conn->insert('usuarios', ['nome' => 'João Silva', 'email' => 'joao@exemplo.com']);
// Seleciona dados
$usuarios = $conn->fetchAllAssociative('SELECT * FROM usuarios');
print_r($usuarios);
Este código cria um banco SQLite, a tabela usuarios, insere um registro e exibe todas as linhas.
4. Principais métodos/funções/classes
4.1. DriverManager::getConnection()
Assinatura: public static function getConnection(array $params, ?Configuration $config = null, ?EventManager $eventManager = null): Connection
O que faz: Cria e retorna um objeto de conexão com o banco de dados com base nos parâmetros fornecidos. É o ponto de entrada do DBAL.
$connectionParams = [
'dbname' => 'meubanco',
'user' => 'root',
'password' => 'senha',
'host' => 'localhost',
'driver' => 'pdo_mysql',
];
$conn = DriverManager::getConnection($connectionParams);
4.2. Connection::executeStatement()
Assinatura: public function executeStatement(string $sql, array $params = [], array $types = []): int
O que faz: Executa uma consulta SQL que não retorna linhas (INSERT, UPDATE, DELETE, DDL). Retorna o número de linhas afetadas.
$linhasAfetadas = $conn->executeStatement('UPDATE usuarios SET nome = ? WHERE id = ?', ['Maria Souza', 1]);
echo "Linhas atualizadas: " . $linhasAfetadas;
4.3. Connection::fetchAllAssociative()
Assinatura: public function fetchAllAssociative(string $sql, array $params = [], array $types = []): array
O que faz: Executa uma consulta SELECT e retorna todas as linhas como um array associativo.
$usuarios = $conn->fetchAllAssociative('SELECT * FROM usuarios WHERE ativo = ?', [1]);
foreach ($usuarios as $usuario) {
echo $usuario['nome'] . ' - ' . $usuario['email'] . "\n";
}
4.4. Connection::fetchOne()
Assinatura: public function fetchOne(string $sql, array $params = [], array $types = []): mixed
O que faz: Executa uma consulta e retorna apenas o valor da primeira coluna da primeira linha. Ideal para consultas de agregação.
$totalUsuarios = $conn->fetchOne('SELECT COUNT(*) FROM usuarios');
echo "Total de usuários: " . $totalUsuarios;
4.5. Connection::insert()
Assinatura: public function insert(string $tableName, array $data, array $types = []): int
O que faz: Método auxiliar para inserir uma linha em uma tabela. Os nomes das colunas são as chaves do array $data.
$conn->insert('usuarios', [
'nome' => 'Carlos Pereira',
'email' => 'carlos@exemplo.com',
'ativo' => 1
]);
4.6. Connection::update()
Assinatura: public function update(string $tableName, array $data, array $where, array $types = []): int
O que faz: Método auxiliar para atualizar linhas em uma tabela com base em uma condição.
$conn->update('usuarios',
['email' => 'novoemail@exemplo.com'],
['id' => 1]
);
4.7. Connection::delete()
Assinatura: public function delete(string $tableName, array $where, array $types = []): int
O que faz: Método auxiliar para deletar linhas de uma tabela com base em uma condição.
$conn->delete('usuarios', ['id' => 1]);
4.8. Query Builder
O Query Builder permite construir consultas SQL complexas de forma programática e segura:
use Doctrine\DBAL\Query\QueryBuilder;
$queryBuilder = $conn->createQueryBuilder();
$queryBuilder
->select('u.id', 'u.nome', 'u.email')
->from('usuarios', 'u')
->where('u.ativo = :ativo')
->setParameter('ativo', 1)
->orderBy('u.nome', 'ASC')
->setMaxResults(10);
$resultados = $queryBuilder->fetchAllAssociative();
5. Conclusão
O Doctrine DBAL é uma ferramenta essencial para qualquer desenvolvedor PHP que trabalha com bancos de dados. Ele oferece o equilíbrio perfeito entre controle total sobre o SQL e produtividade, com recursos como prepared statements, Query Builder e suporte a múltiplos bancos. Seja para projetos pequenos ou grandes sistemas, o DBAL simplifica o acesso a dados sem a complexidade de um ORM completo.
Comece a usar hoje mesmo e veja como ele pode tornar seu código mais limpo, seguro e portável!