Primeiros passos com Doctrine ORM

O Doctrine ORM é um dos projetos mais importantes do conjunto de projetos Doctrine. Ele é um ORM implementado usando o padrão Data Mapper e pode ser usado desde pequenos projetos até grandes aplicações. Pode ser usado em conjunto com grandes frameworks PHP como Symfony, Laravel, Zend, Slim e outros.

Quando falamos de Doctrine a maioria das pessoas já pensa no ORM, porém o Doctrine é um conjunto de projetos para PHP. Temos um post falando sobre os principais projetos do Doctrine, aconselho a leitura antes de prosseguir com este.

Funcionamento e Bancos suportados

O Doctrine ORM funciona sobre outro projeto, o Doctrine DBAL. O DBAL é uma camada de abstração escrita sobre o PDO, ela adiciona uma série de recursos e permite a escrita de código interoperável entre diferentes sistemas gerenciadores de banco de dados.

O Doctrine ORM tira proveito da interoperabilidade do DBAL e da parte de baixo nível do PDO. Essa estrutura permite ao Doctrine ORM suportar os principais gerenciadores de banco de dados:

  • MySQL
  • PostgreSQL
  • SQL Server
  • Oracle
  • SQLite

Mapeamento do banco de dados

Quando vamos usar um ORM a primeira coisa que precisamos fazer é realizar o mapeamento entre as tabelas do modelo relacional para o modelo orientado a objetos. No Doctrine ORM temos 4 opções de notações para descrever as características do banco de dados.

  • Annotations
  • XML
  • PHP
  • YAML

Em aplicações legadas provavelmente encontrará a maioria dos mapeamentos usando XML. Em aplicações mais novas o mapeamento mais utilizado é o através de annotations (comentários que são lidos pelo doctrine).

Entidade

As entidades são usadas para realizar o mapeamento entre o modelo orientado a objetos e o modelo relacional. Por meio delas conseguimos representar exatamente a estrutura do nosso banco de dados. É possível definir nome de tabelas, colunas, chave primária e relacionamentos.

Na imagem abaixo, podemos ver a representação entre o modelo orientado a objetos a esquerda e o modelo relacional a direita:

No projeto as entidades são representadas por classes PHP onde declaramos as propriedades de acordo com a tabela do banco de dados. A entidade produto do exemplo acima, poderia ser representada conforme abaixo:

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\ProductRepository")
 */
class Product
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $nome;

    /**
     * @ORM\Column(type="decimal")
     */
    private $preco;

    /**
     * @ORM\Column(type="text")
     */
    private $descricao;

    public function getId()
    {
        return $this->id;
    }

    public function setNome()
    {
        $this->nome = $nome;
    }

    public function getNome()
    {
        return $this->nome;
    }

    public function setPreco()
    {
        $this->preco = $preco;
    }

    public function getPreco()
    {
        return $this->preco;
    }

    public function setDescricao()
    {
        $this->descricao = $descricao;
    }

    public function getDescricao()
    {
        return $this->descricao;
    }
}

Note que os comentários na classe acima iniciam com @ORM. Esses comentário são as informações de mapeamento definidas através de annotations.

Entity Manager

Se verificar novamente a entidade que mapeamos, verá que ela não estende nenhuma classe da estrutura do Doctrine, ela é apenas uma classe do PHP. Desse modo, para que possamos através dela manipular qualquer informação no banco de dados precisamos de uma classe específica do Doctrine, a Entity Manager.

A Entity Manager ou em português gerenciador de entidades, é a classe do doctrine responsável por gerenciar o estado das entidades e realizar as escritas no banco de dados. Ela implementa um padrão chamado Unit of Work ou em português unidade de trabalho, esse padrão mantém uma lista das alterações realizadas nas entidades monitoradas pelo Entity Manager em memória e organiza a parte de escrita dessas alterações no banco de dados de forma consistente, quando solicitado.

Obtendo a instância do Entity Manager

O processo de obtenção da instância da classe Entity Manager vai depender muito de onde está usando o Doctrine. Abaixo alguns links de referência para alguns frameworks:

Se estiver usando o Doctrine sem nenhum Framework terá algo parecido com isso:

require_once "vendor/autoload.php";

use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;

$paths = [__DIR__."/src/Entities"];
$isDevMode = true;
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode, null, null, false);

//aqui configuramos a conexão com banco de dados
$params = [
    'url' => "mysql://usuario:senha@servidor/nome-banco"
];

//Obter a instância da classe Entity Manager
$entityManager = EntityManager::create($params, $config);

Lembrando que para o exemplo acima funcionar é necessário instalar o pacote do Doctrine ORM usando o composer:

composer require doctrine/orm

Persistindo dados

Usamos o Entity Manager para persistir informações no banco de dados. Vamos criar um novo registro no banco de dados através da entidade que defimos chamada produto.

Primeira coisa precisamos criar uma instância e definir os dados do produto:

$produto = new Produto;

$produto->setNome('Bicicleta');
$produto->setPreco(800);
$produto->setDescricao('Engrenagem fixa, azul, rápida')

Veja que estamos usando métodos setters. Isso porque nossas propriedades da entidade são sempre privadas, com isso precisamos usar os métodos setters e getters para conseguir manipular os valores.

Agora com a instância da entidade produto já definida, podemos indicar ao Entity Manager que ela deve ser persistida no banco de dados:

$entityManager->persist($produto);

No exemplo a instância da classe Entity Manager está dentro da variável $entityManager, mas poderia ser qualquer nome, dependendo de onde está usando. O importante é entender o que o método persist está fazendo, indicando que a instância deve ser monitorada.

Por fim, precisamos pedir para o Entity Manager realizar as alterações no banco de dados, pois até agora os dados estão apenas em memória. Para isso usamos o método flush:

$entityManager->flush();

Pronto! Se tiver a tabela corretamente criada e os parâmetros de conexão estiverem certos, verá o registro no banco de dados.

Considerações Finais

O Doctrine é um ORM extremamente poderoso com dezenas de recursos. Nos próximos posts vamos aprender os diferentes modos de consultar informações no banco de dados e também como configurar relações.

Deixe seu comentário

Professor e desenvolvedor. Formado em análise e desenvolvimento de sistema, pós graduando em engenharia e arquitetura de software. É autor de cursos em diversos temas, como, desenvolvimento back-end, cloud computing e CMSs. Nas horas vagas adora estudar sobre o mercado financeiro, cozinhar e brincar com pequeno Daniel. @eltonfonsecadev