PHP

Substituindo o PDO por Doctrine DBAL

Por em

O PDO é uma biblioteca PHP de abstração de dados para trabalhar com banco de dados, desde que ela foi lançada no PHP 5, mudou-se a forma de como manipular a comunicação com banco de dados, trazendo inúmeras melhorias. A primeira claramente, é deixando a manipulação procedural de lado para focar na orientação a objetos e também as melhorias quanto a facilidade de manipulação de dados. Mas ainda assim, trabalhar com SQL puro pode se tornar maçante e/ou chato, porque, às vezes os comandos são grandes e/ou complexos, dando margem para erros que atrasam nosso desenvolvimento e manutenção das aplicações. O PDO é fantástico para manipular banco de dados, porém, para um banco de dados mais complexo, ele pode não ser adequado, por isto, mostro uma alternativa para trabalhar no topo dele.

Qual é a ideia?

Usaremos o Doctrine DBAL, que é um componente do framework Doctrine, este componente é uma abstração de dados acima do PDO, ou seja, abstrai mais ainda a manipulação do banco de dados. No final das contas, por trás, ele usa o PDO mesmo, mas, traz uma abstração absurda quanto a manipulação das queries.

O que faremos?

  1. Instalar o Composer
  2. Criar uma aplicação com o DBAL
  3. Mostrar o uso do DBAL.
  4. Considerações finais. 

Passos

  1. Instalar o Composer.

Se você não conhece, o Composer é um gerenciador de dependências de bibliotecas PHP, semelhante ao RubyGems do Ruby. Ele faz a instalação de bibliotecas pré-registradas e suas dependências, além, de fazer um carregamento automático de tudo que precisamos para executar nossa aplicação.

Existem muitas maneiras de instala-lo, confira aqui. Para ganharmos tempo irei instalar usando PHP puro. Crie uma pasta para nosso novo projeto e execute este comando na raiz:

php -r "readfile('https://getcomposer.org/installer');" | php

Isto baixará o arquivo composer.phar que nós permitirá usar o Composer.

  1. Criar uma aplicação com o DBAL.

Agora vamos criar nossa aplicação com o Composer e instalar o DBAL, faça:

php composer.phar require doctrine/dbal:~2.3

Isto criará nossa aplicação e instalará como dependência o DBAL versão >= 2.3 e <3.0 e suas dependências.

Vamos criar um arquivo index.php na raiz do projeto, iniciar o DBAL e passar as configurações de banco de dados:

require_once __DIR__ . '/vendor/autoload.php';

$config = new \Doctrine\DBAL\Configuration();

$connectionParams = array(
    'dbname' => 'code_dbal',
    'user' => 'root',
    'password' => 'root',
    'host' => 'localhost',
    'port' => 3306,
    'charset' => 'utf8',
    'driver' => 'pdo_mysql',
);
$dbh = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config);

 Na primeira linha iniciamos o carregamento do que precisamos na aplicação, então, posteriormente não precisaremos ficar importando nada com includes e requires. Mais abaixo configuramos a conexão do DBAL com banco de dados.

  1. Mostrar uso do DBAL

Para ganharmos tempo, criei um pequeno script no mysql para podermos fazer transações no banco de dados. No final do post você poderá ver todo código criado e o script do banco. O banco tem duas tabelas: categorias e produtos (todo produto terá uma categoria).

A priori criar as queries com DBAL é bem semelhante ao PDO:

//Pegar uma categoria
$statement = $dbh->query("SELECT * FROM categorias WHERE id = 1");
$categoria = $statement->fetch();
var_dump($categoria);

//Pegar todas categorias
$statement = $dbh->query("SELECT * FROM categorias");
$categorias = $statement->fetchAll();
var_dump($categorias);

//Pegar um campo de um produto
$statement = $dbh->query("SELECT nome FROM produtos WHERE id = 1");
$nome = $statement->fetchColumn();
echo $nome;

//Pegar coleção de nomes em array
$statement = $dbh->query("SELECT nome FROM produtos");
$nomes = $statement->fetchAll(\PDO::FETCH_COLUMN);
var_dump($nomes);

//Pegar coleção de categorias em array key => value
$statement = $dbh->query("SELECT id, nome FROM categorias");
$categorias = $statement->fetchAll(\PDO::FETCH_KEY_PAIR);
var_dump($categorias);

Mas, a primeira vantagem do DBAL sobre o PDO, é que o DBAL quando instanciado não realiza conexão com banco de dados até que uma primeira query seja executada, já o PDO não.

Outra vantagem é o ganho para se criar INSERTS, UPDATES E DELETES, veja como a sintaxe é mais simples:

//Para incluir uma categoria
$dbh->insert('categorias', array('nome' => 'Minha categoria'));

//Para incluir uma categoria
$dbh->update('categorias', array('nome' => 'Minha categoria atualizada'), array('id' => 1));

//Para excluir um produto
$dbh->delete('produtos', array('id' => 1));

Agora vou mostrar a minha funcionalidade preferida, que é o QueryBuilder. Ele alivia e muito o trabalho de criar querys complexas, com muitas regras e joins. Vamos criar algumas querys:

//Pegar produtos que tem a categoria 2
$query = $dbh->createQueryBuilder();
$query->select('p.*')
    ->from('produtos', 'p')
    ->where('p.categoria_id = :categoria')
    ->setParameter(':categoria', 2);
;
$statement = $query->execute();
$produtos = $statement->fetch();
var_dump($produtos);

//Pegar todos produtos e suas respectivas categorias
$query = $dbh->createQueryBuilder();
$query->select('p.nome as produto,c.nome as categoria')
    ->from('produtos', 'p')
    ->leftJoin('p','categorias','c','c.id = p.categoria_id');
;
$statement = $query->execute();
$produtos = $statement->fetch();
print_r($produtos);

O QueryBuilder facilita nosso trabalho, porque abstrai a escrita de SQL puro, não temos que escrever uma query inteira em string, podemos trabalhar de forma orientada a objetos. Ele já tem todas funções que precisamos: where, order by, joins, select, group by, froms, etc.

  1. Considerações finais

É isso aí pessoal, espero que tenham gostado e que comecem a usar o DBAL para facilitar a vida com o trabalho com banco de dados. Baixem o código deste tutorial, criem novas tabelas, novas queries e confirmem esta ferramenta fantástica que é o Doctrine DBAL.

Referências:

http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html

http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/data-retrieval-and-manipulation.html

http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/query-builder.html