Code Monkey home page Code Monkey logo

orm's Introduction

Lumberjack's ORM

Intodução

Lumberjack's ORM é um framework ORM para a linguagem PHP. ORM é uma sigla em inglês que significa Object-Relational Mapper. Um ORM é uma ferramenta bastante útil no dia-a-dia do desenvolvedor de software.

O Lumberjack's ORM trabalha com mapeamento de tabelas em classes do modelo de dados utilizando Annotations. O ORM permite ao desenvolvedor trabalhar com mais de uma conexão de banco de dados e criar as tabelas do banco de dados baseado nas classes do modelo.

Tabela de Conteúdos

1. INSTALAÇÃO

Para usar o Lumberjack's ORM, pode-se obtê-lo no repositório orm no GitHub no link: https://github.com/dfrancklin/orm.

Basta então copiar a pasta /orm que foi baixada e para incluir o ORM no projeto, use o comando require_once:

Código Exemplo 1: Incluir o ORM ao projeto

<?php
    require_once './orm/load.php';
?>

Voltar

2. DEFININDO CONEXÕES

As conexões que serão utilizadas pelo ORM devem ser declaradas em um arquivo com extensão .php. Por padrão, o arquivo é esperado que esteja na pasta raiz do ORM com o nome connection.config.php, ou seja, supondo que o ORM esteja localizado /home/user/app/orm/, então o caminho para o arquivo seria /home/user/app/orm/connection.config.php.

O arquivo de conexões pode ser substituído da seguinte maneira:

Código Exemplo 2: Definindo qual arquivo de conexões o ORM utilizará

<?php
    $orm = ORM\Orm::getInstance();
    $orm->setConnectionsFile(__DIR__ . '/db/connections.php');
?>

O arquivo deve conter um array com uma ou mais conexões, onde a chave da conexão é o nome identificador da conexão e o valor é um array contendo as informações da conexão. As informações variam de acordo com o banco de dados a ser utilizado.

Código Exemplo 3: Definindo arquivo de conexões

<?php
    return [
        'exemplo-mysql' => [
            'db' => 'mysql',
            'version' => '5.7.11',
            'host' => 'localhost',
            'schema' => 'app',
            'user' => 'root'
            'pass' => 'root'
        ],
        'exemplo-sqlite' => [
            'db' => 'sqlite',
            'version' => '3',
            'file' => '../data/app-storage.sq3',
        ],
    ];
?>

Os valores para a conexão exemplo-mysql é um array contendo as chaves db, version, host, schema, user e pass. A chave db contém o banco de dados a ser utilizado. A chave version indica a versão do banco de dados utilizado, no qual o Driver deve corresponder à essa versão. A chave host é o endereço onde o banco de dados está localizado. A chave schema é o banco de dados (conjunto de tabelas) que será utilizado. As chaves user e pass são respectivamente o usuário e a senha de acesso ao banco de dados.

Os valores para a conexão exemplo-sqlite é um array contendo as chaves db, version, file. As chaves db e version funcionam da mesma maneira que a conexão anterior. A chave file indica o arquivo local o qual o banco de dados SQLite utilizará para armazenar os dados.

Para informar ao ORM qual (ou quais) conexão será utilizada na aplicação, deve ser feito através da classe principal do ORM conforme o exemplo a seguir:

Código Exemplo 4: Definindo conexões que o ORM poderá utilizar

<?php
    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $orm->addConnection('exemplo-sqlite');
?>

O método setConnection adiciona a conexão à lista de conexões que o ORM pode utilizar e faz com que a conexão informada seja a conexão padrão para o ORM, ou seja, qualquer operação que será realizada pelo ORM, se não for informada uma conexão explicitamente, o ORM irá assumir que a conexão que precisa ser usada é a conexão padrão.

Já o método addConnection apenas adiciona a conexão à lista de conexões que o ORM pode utilizar. A conexão padrão pode ser substituída a qualquer momento, para isso basta utilizar o método setDefaultConnection:   Código Exemplo 5: Definindo conexões que o ORM poderá utilizar

<?php
    $orm = ORM\Orm::getInstance();
    $orm->addConnection('exemplo-mysql');
    $orm->setDefaultConnection('exemplo-mysql');
?>

Voltar

2.1. Criar Tabelas Automaticamente


O ORM tem a habilidade de criar as tabelas a partir das classes modelo. Para que o ORM saiba como criar, é necessário informar o caminho para a pasta que contém os modelos e o namespace no momento em que estiver configurando a conexão no ORM. Por exemplo:

Código Exemplo 6: Definindo criação de tabelas no ORM

<?php
    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql', [
        'namespace' => 'App\\Models',
        'modelsFolder' => '/home/user/app/models',
        'create' => true
    ]);
?>

Pode ser necessário também, apagar as tabelas antes de criá-las, para isso, basta informar também na configuração da conexão:

Código Exemplo 7: Definindo criação e deleção de tabelas no ORM

<?php
    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql', [
        'namespace' => 'App\\Models',
        'modelsFolder' => '/home/user/app/models',
        'create' => true,
        'drop' => true
    ]);
?>

O ORM permite ainda, que uma ação seja executada antes de apagar as tabelas e uma ação após criar as tabelas. Essas ações podem ser úteis para criar uma rotina de backup/restore ou de migração de banco de dados. Para informar ao ORM quais ações ele deve executar, basta fazer o seguinte:

Código Exemplo 8: Definindo ação para executar antes criação e da deleção de tabelas no ORM

<?php
    $dbHelper = new App\Helpers\InitDatabase();
    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql', [
        'namespace' => 'App\\Models',
        'modelsFolder' => '/home/user/app/models',
        'drop' => true,
        'create' => true,
        'beforeDrop' => [ $dbHelper, 'beforeDrop' ],
        'afterCreate' => [ $dbHelper, 'afterCreate' ]
    ]);
?>

Na linha 2, é criada uma instância da classe App\Helpers\InitDatabase e nas linhas 9 e 10, são informados, para a conexão respectivamente, quais métodos devem ser executados antes de apagar as tabelas e depois de criá-las. Utilizando esses métodos é possível que o desenvolvedor crie uma lógica de como realizar o backup das informações essenciais do banco de dados antes de apagar as tabelas e posteriormente restaurar essas informações após a criação das tabelas.

Os valores esperados pelas chaves beforeDrop e afterCreate podem ser também uma função anônima:

Código Exemplo 9: Definindo ação para executar antes criação e da deleção de tabelas no ORM

<?php
    ...
        'beforeDrop' => function($entityManager) { ... },
        'afterCreate' => function($entityManager) { ... }
    ...
?>

Ou uma string contendo o nome de uma função:

Código Exemplo 10: Definindo ação para executar antes criação e da deleção de tabelas no ORM

<?php
    ...
        'beforeDrop' => 'beforeDrop',
        'afterCreate' => 'afterCreate'
    ...

    function beforeDrop($entityManager) { ... }
    function afterCreate($entityManager) { ... }
?>

O ORM passa uma instância de um EntityManager por parâmetro para os métodos ou funções que serão executadas antes e depois do processo de criação das tabelas. Ele pode ser usado para realizar ações no banco de dados. O EntityManager será abordado mais à frente.

Voltar

3. DEFININDO MODELOS

Um modelo é uma classe que representa uma tabela no banco de dados e pode ser mapeada da classe para a tabela e da tabela para a classe em operações de consulta, inserção, alteração e deleção.

Para que um modelo possa representar devidamente uma tabela no banco de dados dentro do ORM, ela deve ser "anotada" utilizando o padrão de annotation definido pelo ORM.

Voltar

3.1. Annotations


As annotations são "etiquetas" que adicionam metadados relevantes sobre classes, métodos e propriedades. Ou seja, através do uso de annotations, pode-se adicionar às classes informações para mapear tabelas do banco de dados, e adicionar às propriedades da classe para mapear as colunas de uma tabela do banco de dados, para que posteriormente, em tempo de execução, os metadados indicados pelas annotations sejam analisados e a partir disso, o ORM irá trabalhar de acordo com essas informações.

Abaixo, uma lista completa das annotations e suas propriedades:

Voltar

3.1.1. Annotations de Classes


  • Annotation: @ORM/Entity.

    Descrição: Define que a classe deve ser considerada como uma tabela no banco de dados.

    Preenchimento: Obrigatório. O não preenchimento resulta em erro.

  • Annotation: @ORM/Table.

    Descrição: Define informações sobre a tabela mapeada.

    Preenchimento: Opcional.

    Propriedades:

    • Nome: name.

      Descrição: Define o nome da tabela mapeada.

      Preenchimento: Opcional. Caso não preenchido, o ORM assume que o nome da tabela é o mesmo que o nome da classe.

    • Nome: schema.

      Descrição: Define qual é o conjunto de tabelas ou banco de dados ao qual a tabela mapeada em questão existe.

      Preenchimento: Opcional. Caso não preenchido, o ORM assume que o schema a ser usado é o padrão definido na conexão ou nenhum, dependendo do banco de dados usado.

    • Nome: mutable.

      Descrição: Caso o valor seja true define que a tabela não pode ser modificada pelas operações de inserção, alteração e deleção. O valor padrão é false. Normalmente utilizado para mapear uma view.

      Preenchimento: Opcional. Assume o valor padrão caso não seja preenchido.

Voltar

3.1.2. Annotations de Propriedades


  • Annotation: @ORM/Id.

    Descrição: Define que a propriedade representa a chave primária da tabela mapeada.

    Preenchimento: Obrigatório. O não preenchimento resulta em erro.

  • Annotation: @ORM/Generated.

    Descrição: Define que o valor da chave primaria é auto gerado, seja através de sequence ou qualquer tipo de autoincrement (isso é definido no driver para cada banco de dados).

    Preenchimento: Opcional. O não preenchimento indica que o preenchimento e o incremento deverão ser feitos manualmente.

  • Annotation: @ORM/Column.

    Descrição: Define informações sobre a coluna ser mapeada.

    Preenchimento: Opcional. Assume os valores padrões das propriedades listadas a seguir.

    Propriedades:

    • Nome: name.

      Descrição: Define o nome da coluna a ser mapeada.

      Preenchimento: Opcional. Caso não seja preenchido, o ORM assume que o nome da coluna é o mesmo nome do atributo.

    • Nome: type.

      Descrição: Define o tipo da coluna a ser mapeada.

      Tipos: string, int, float, lob (large object), date, time, datetime, bool.

      Preenchimento: Opcional. Caso não seja preenchido, o ORM assume que o tipo da coluna é string.

    • Nome: length.

      Descrição: Define o tamanho da coluna a ser mapeada quando a coluna é do tipo string.

      Preenchimento: Opcional. Caso não seja preenchido, o ORM assume que o tamanho da coluna é 255.

    • Nome: scale.

      Descrição: Define o tamanho da coluna a ser mapeada quando a coluna é do tipo float.

      Preenchimento: Opcional. Caso não seja preenchido, o ORM assume que o tamanho da coluna é 14.

    • Nome: precision.

      Descrição: Define a precisão da coluna (quantidade de dígitos após a virgula) a ser mapeada quando a coluna é do tipo float.

      Preenchimento: Opcional. Caso não seja preenchido, o ORM assume que a precisão da coluna é 2.

    • Nome: unique.

      Descrição: Se o valor do campo for true, define que o campo deve ser conter um valor único.

      Preenchimento: Opcional. Valor padrão é false.

    • Nome: nullable.

      Descrição: Se o valor do campo for false, define que o campo não pode receber valores nulos.

      Preenchimento: Opcional. Valor padrão é true.

Voltar

3.1.3. Annotations de Relacionamentos


  • Annotation: @ORM/HasOne.

    Descrição: Define um relacionamento do tipo "um para um". É necessário que a classe de referência tem um atributo equivalente à outra ponta do relacionamento com a annotation @ORM/BelongsTo.

    Preenchimento: Opcional.

    Propriedades:

    • Nome: class.

      Descrição: Define qual classe deve ser referenciada no mapeamento.

      Preenchimento: Obrigatório. O não preenchimento resulta em erro.

    • Nome: cascade.

      Descrição: Define que as operações de inserção, alteração e deleção pode acontecer em cascata, ou seja, a operação realizada na classe que mapeia essa annotation, deve ser estendida para a classe referenciada.

      Valores: INSERT, UPDATE, DELETE, ALL.

      Preenchimento: Opcional. Caso não seja preenchida, a operação não é estendida.

  • Annotation: @ORM/HasMany.

    Descrição: Define um relacionamento do tipo "um para muitos". É necessário que a classe de referência tem um atributo equivalente à outra ponta do relacionamento com a annotation @ORM/BelongsTo.

    Preenchimento: Opcional.

    Propriedades:

    • Nome: class.

      Descrição: Define qual classe deve ser referenciada no mapeamento.

      Preenchimento: Obrigatório. O não preenchimento resulta em erro.

    • Nome: cascade.

      Descrição: Define que as operações de inserção, alteração e deleção pode acontecer em cascata, ou seja, a operação realizada na classe que mapeia essa annotation, deve ser estendida para a classe referenciada.

      Valores: INSERT, UPDATE, DELETE, ALL.

      Preenchimento: Opcional. Caso não seja preenchida, a operação não é estendida.

  • Annotation: @ORM/BelongsTo.

    Descrição: Define a outra ponta dos relacionamentos do tipo "um para um" e do tipo "um para muitos", ou seja, define a chave estrangeira para o relacionamento. É necessário que a classe de referência tem um atributo equivalente à outra ponta do relacionamento com a annotation @ORM/HasOne ou @ORM/HasMany.

    Preenchimento: Caso uma relação do tipo "um para um" ou do tipo "um para muitos" seja definida, é obrigatório que a classe referenciada possua essa annotation.

    Propriedades:

    • Nome: class.

      Descrição: Define qual classe deve ser referenciada no mapeamento.

      Preenchimento: Obrigatório. O Não preenchimento resulta em erro.

    • Nome: cascade.

      Descrição: Define que as operações de inserção, alteração e deleção pode acontecer em cascata, ou seja, a operação realizada na classe que mapeia essa annotation, deve ser estendida para a classe referenciada.

      Valores: INSERT, UPDATE, DELETE, ALL.

      Preenchimento: Opcional. Caso não seja preenchida, a operação não é estendida.

    • Nome: optional.

      Descrição: Define se o relacionamento é opcional, ou seja, indica que o valor pode ou não ser nulo.

      Preenchimento: Opcional. Valor padrão é "false".

  • Annotation: @ORM/JoinColumn.

    Descrição: Define as informações da coluna que deve ser a chave estrangeira. Somente a propriedade que possui a annotation @ORM/BelongsTo deve possuir essa annotation para complementar as informações.

    Preenchimento: Opcional. Assume os valores padrões das propriedades listadas a seguir.

    Propriedades:

    • Nome: name.

      Descrição: Define o nome da coluna a ser mapeada como chave estrangeira.

      Preenchimento: Opcional. O valor padrão é o nome da propriedade mais o sufixo "_id", por exemplo, "pessoa_id".

  • Annotation: @ORM/ManyToMany.

    Descrição: Define um relacionamento de do tipo "muitos para muitos". É necessário que a classe de referência tem um atributo equivalente à outra ponta do relacionamento com a annotation @ORM/ManyToMany.

    Preenchimento: Caso uma relação do tipo "muitos para muitos" seja definida, é obrigatório que a classe referenciada possua essa annotation.

    Propriedades:

    • Nome: class.

      Descrição: Define qual classe deve ser referenciada no mapeamento.

      Preenchimento: Obrigatório. O não preenchimento resulta em erro.

    • Nome: cascade.

      Descrição: Define que as operações de inserção, alteração e deleção pode acontecer em cascata, ou seja, a operação realizada na classe que mapeia essa annotation, deve ser estendida para a classe referenciada.

      Valores: INSERT, UPDATE, DELETE, ALL.

      Preenchimento: Opcional. Caso não seja preenchida, a operação não é estendida.

    • Nome: mappedBy.

      Descrição: Define que o lado principal do mapeamento é a classe referenciada e define também qual é o atributo ao qual é o equivalente. O lado principal pode definir também as informações da tabela de ligação.

      Preenchimento: Opcional.

  • Annotation: @ORM/JoinTable.

    Descrição: Define informações para a tabela de ligação. Somente o lado principal do relacionamento deve possuir essa annotation para complementar as informações.

    Preenchimento: Opcional. Assume os valores padrões das propriedades listadas a seguir.

    Propriedades:

    • Nome: tableName.

      Descrição: Define o nome da tabela de ligação.

      Preenchimento: Opcional. O valor padrão e composto pelo nome das duas tabelas que compõe o relacionamento, por exemplo, "empregado_role".

    • Nome: schema.

      Descrição: Define qual é o conjunto de tabelas ou banco de dados ao qual a tabela de ligação em questão existe.

      Preenchimento: Opcional. Caso não preenchido, o ORM assume que o schema a ser usado é o padrão definido na conexão ou nenhum, dependendo do banco de dados usado.

    • Nome: join.

      Descrição: Define o nome da coluna que é a chave estrangeira que aponta para o lado principal do relacionamento.

      Preenchimento: Opcional. Assume os valores padrões das propriedades listadas a seguir.

      Propriedades:

      • Nome: name.

        Descrição: Define o nome da coluna a ser mapeada como chave estrangeira.

        Preenchimento: Opcional. O valor padrão é o nome da propriedade mais o sufixo "_id", por exemplo, "empregado_id".

    • Nome: inverse.

      Descrição: Define o nome da coluna que é a chave estrangeira que aponta para o lado secundário do relacionamento.

      Preenchimento: Opcional. Assume os valores padrões das propriedades listadas a seguir.

      Propriedades:

      • Nome: name.

        Descrição: Define o nome da coluna a ser mapeada como chave estrangeira.

        Preenchimento: Opcional. O valor padrão é o nome da propriedade mais o sufixo "_id", por exemplo, "role_id".

Voltar

3.2. Exemplo de Mapeamento Simples


Um exemplo básico de como criar uma classe do modelo, pode ser encontrado no exemplo a seguir. A classe "Empregado" mapeia a tabela "empregados" no banco de dados:

Código Exemplo 11: Exemplo de classe do modelo mapeada

<?php

namespace App\Models;

/**
 * @ORM/Entity
 * @ORM/Table(name=empregados)
 */
class Empregado {

    /**
     * @ORM/Id
     * @ORM/Generated
     * @ORM/Column(name=empregado_id, type=int)
     */
    public $id;

    /**
     * @ORM/Column(type=string, length=50)
     */
    public $nome;

    /**
     * @ORM/Column(name=data_nasc, type=date)
     */
    public $dataNasc;

}

O exemplo acima, de acordo com a Código Exemplo 11, exibe o mapeamento da classe "Empregado", ela representa a tabela "empregados" e possui os atributos $id (chave primária do tipo inteiro e com o nome da coluna "empregado_id"), $nome (tipo texto com o tamanho 50) e $dataNasc (tipo data com o nome da coluna "data_nasc").

Voltar

3.3. Exemplos de Mapeamento de Relacionamentos


Relacionamento entre tabelas é um recurso essencial nos bancos de dados, para representar isso devidamente, no mundo orientado a objetos, existe as seguintes opções.

Voltar

3.3.1. Um para Um


Um exemplo básico de como mapear um relacionamento do tipo "um para um", pode ser encontrado no exemplo a seguir. A classe "Empregado" mapeia o relacionamento através do atributo $informacoes:

Código Exemplo 12: Exemplo de relacionamento "um para um"

<?php

namespace App\Models;

/**
 * @ORM/Entity
 * @ORM/Table(name=empregados)
 */
class Empregado {

    ...

    /**
     * @ORM/HasOne(class=App\Models\EmpregadoInfo, cascade={ALL})
     */
    public $informacao;

    ...

}

O exemplo acima, de acordo com a Código Exemplo 12, exibe o mapeamento da classe "Empregado", ela representa a tabela "empregados" e possui o atributo $informacao, que por sua vez, mapeia o relacionamento do tipo "um para um" com a classe "EmpregadoInfo".

A classe "EmpregadoInfo" referenciada pela classe "Empregado" seria:

Código Exemplo 13: Exemplo de relacionamento "um para um" (outra ponta)

<?php

namespace App\Models;

/**
 * @ORM/Entity
 * @ORM/Table(name=empregado_info)
 */
class EmpregadoInfo {

    ...

    /**
     * @ORM/BelongsTo(class=App\Models\Empregado)
     * @ORM/JoinColumn(name=empregado_id)
     */
    public $empregado;

    ...

}

O exemplo acima, de acordo com a Código Exemplo 13, exibe o mapeamento da classe "EmpregadoInfo", ela representa a tabela "empregado_info" e possui o atributo $empregado, que por sua vez, mapeia a outra ponta o relacionamento do tipo "um para um" com a classe "Empregado" e mapeia a coluna "empregado_id" da tabela "pedido".

Voltar

3.3.2. Um para Muitos


Um exemplo básico de como mapear um relacionamento do tipo "um para muitos", pode ser encontrado no exemplo a seguir. A classe "Cliente" mapeia o relacionamento através do atributo $pedidos:

Código Exemplo 14: Exemplo de relacionamento "um para muitos"

<?php

namespace App\Models;

/**
 * @ORM/Entity
 */
class Cliente {

    ...

    /**
     * @ORM/HasMany(class=App\Models\Pedido)
     */
    public $pedidos;

    ...

}

O exemplo acima, de acordo com a Código Exemplo 14, exibe o mapeamento da classe "Cliente", ela representa a tabela "cliente" e possui o atributo $pedidos, que por sua vez, mapeia o relacionamento do tipo "um para muitos" com a classe "Pedido".

A classe "Pedido" referenciada pela classe "Cliente" seria:

Código Exemplo 15: Exemplo de relacionamento "um para muitos" (outra ponta)

<?php

namespace App\Models;

/**
 * @ORM/Entity
 */
class Pedido {

    ...

    /**
     * @ORM/BelongsTo(class=App\Models\Cliente)
     */
    public $cliente;

    ...

}

O exemplo acima, de acordo com a Código Exemplo 15, exibe o mapeamento da classe "Pedido", ela representa a tabela "pedido" e possui o atributo $cliente, que por sua vez, mapeia a outra ponta o relacionamento do tipo "um para muitos" com a classe "Cliente" e mapeia a coluna "cliente_id" da tabela "pedido".

Voltar

3.3.3. Muitos para Muitos


Um exemplo básico de como mapear um relacionamento do tipo "muitos para muitos", pode ser encontrado no exemplo a seguir. A classe "Empregado" mapeia o relacionamento através do atributo $projetos:

Código Exemplo 16: Exemplo de relacionamento "muitos para muitos"

<?php

namespace App\Models;

/**
 * @ORM/Entity
 */
class Empregado {

    ...

    /**
     * @ORM/ManyToMany(class=App\Models\Projeto)
     * @ORM/JoinTable(tableName=empregado_projeto, join={ name=empregado_id }, join={ name=projeto_id })
     */
    public $projetos;

    ...

}

O exemplo acima, de acordo com a Código Exemplo 16, exibe o mapeamento da classe "Empregado", ela representa a tabela "empregado" e possui o atributo $projetos, que por sua vez, mapeia o relacionamento do tipo "muitos para muitos" com a classe "Projeto" e é o lado principal do relacionamento, isso quer dizer que é o lado do relacionamento que define as informações da tabela de ligação.

A classe "Projeto" referenciada pela classe "Empregado" seria:

Código Exemplo 17: Exemplo de relacionamento "muitos para muitos" (outra ponta)

<?php

namespace App\Models;

/**
 * @ORM/Entity
 */
class Projeto {

    ...

    /**
     * @ORM/ManyToMany(class=App\Models\Empregado, mappedBy=projetos)
     */
    public $empregados;

    ...

}

O exemplo acima, de acordo com a Código Exemplo 17, exibe o mapeamento da classe "Projeto", ela representa a tabela "projeto" e possui o atributo $empregados, que por sua vez, mapeia a outra ponta o relacionamento do tipo "muitos para muitos" com a classe "Empregado" e indica que a tabela de ligação é mapeada pelo atributo $projetos.

Voltar

4. ENTITY MANAGER

O EntityManager é o gerenciador de entidades do ORM, através dele é que o desenvolvedor tem acesso às funções de consulta, persistência e deleção.

Essa seção irá abordar as funcionalidades que envolvem o EntityManager.

Voltar

4.1. Obtendo Uma Instância do EntityManager


Para obter uma instância, basta que o ORM crie uma, da seguinte maneira:   Código Exemplo 18: Exemplo de como obter uma instância do EntityManager

<?php
    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $orm->addConnection('exemplo-sqlite');
    $em = $orm->createEntityManager();
?>

O método createEntityManager retorna uma instância do EntityManager utilizando a conexão padrão do ORM, ou seja, todas as operações realizadas no EntityManager serão realizadas através da conexão padrão, no caso do exemplo acima, de acordo com a Código Exemplo 18, a conexão "exemplo-mysql".

Para utilizar uma conexão secundária, é necessário passar o nome da conexão para o método createEntityManager:

Código Exemplo 19: Exemplo de como obter uma instância do EntityManager com conexão segundária

<?php
    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $orm->addConnection('exemplo-sqlite');
    $em = $orm->createEntityManager('exemplo-sqlite');
?>

Agora o método createEntityManager irá retorna uma instância do EntityManager utilizando a conexão secundária "exemplo-sqlite".

Voltar

4.2. Transações


A transação no banco de dados, é uma unidade que realiza um trabalho, ou seja, qualquer trabalho realizado no banco de dados, mesmo que em etapas, é realizado dentro de uma transação e todas as operações realizadas dentro dessa transação tem a garantia de ser executada integralmente no banco de dados, isso significa que caso um problema ocorra durante a execução de uma transação, as operações já realizadas dentro da mesma transação serão desfeitas.

Bernstein (2009) define que uma transação de banco de dados deve ser atômica, consistente, isolada e durável conhecido pela sigla ACID:

  • Atômica: uma série indivisível e irredutível de operações de banco de dados;
  • Consistente: toda e qualquer transação deve alterar os dados no banco apenas de formas permitidas, ou seja, quaisquer dados gravados devem ser válidos de acordo com todas as regras definidas na tabela;
  • Isolada: determina como a integridade da transação é visível para outros usuários e sistemas;
  • Durável: garante que as transações que foram confirmadas sobreviverão permanentemente no banco de dados.

Voltar

4.2.1. BeginTransaction


Para iniciar uma transação no ORM, o desenvolvedor deve usar o método beginTransaction.

Código Exemplo 20: Exemplo de como iniciar uma trasação

<?php
    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $em->beginTransaction();
?>

O método beginTransaction irá criar iniciar uma transação para a conexão padrão do ORM. Para fechar a transação, o desenvolvedor deverá executar o método commit ou o método rollback.

Voltar

4.2.2. Commit


O método commit irá confirmar a transação atual para que as operações realizadas no banco de dados sejam efetivadas. Liberando assim o EntityManager para criar uma nova transação.

Código Exemplo 21: Exemplo de como aplicar alterações de uma trasação

<?php
    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $em->beginTransaction();
    // operações no banco de dados, por exemplo, um insert
    $em->commit();
?>

Voltar

4.2.3. Rollback


O método rollback irá desfazer as operações realizadas na transação atual, liberando assim o EntityManager para criar uma nova transação. Esse método é normalmente utilizado em um try/catch para tratamento de erros.

Código Exemplo 22: Exemplo de como desfazer alterações de uma trasação

<?php
    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();

    try {
        $em->beginTransaction();
        // operações no banco de dados
        $em->commit();
    } catch(Exception $ex) {
        $em->rollback();
    }
?>

Voltar

4.3. Find


O método find é utilizado para carregar um registro do banco de dados através da chave primária dessa tabela.

Código Exemplo 23: Exemplo de como carregar registro por chave primária

<?php
    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $id = 1;
    $empr = $em->find(App\Models\Empregado::class, $id);
?>

O método find espera como parâmetro a classe que mapeia a tabela a ser utilizada na consulta e a chave primária correspondente ao registro necessário.

Voltar

4.4. List


O método list é utilizado para carregar uma lista de registros do banco de dados, porém, sem utilizar filtros (clausula where).

Código Exemplo 24: Exemplo de como listar os registro de uma dada tabela

<?php
    use App\Models\Empregado;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();

    $emprs = $em->list(Empregado::class);
    $emprs = $em->list(Empregado::class, 15);
    $emprs = $em->list(Empregado::class, 2, 10);
?>

O método list pode ser usado de três formas. A primeira, passando como parâmetro somente a classe que mapeia a tabela a ser listada, e traz todos os registros que estão atualmente na tabela. A segunda, passando como parâmetro a classe que mapeia a tabela a ser lista e a quantidade de registros a serem carregados pela consulta, no caso do exemplo, os primeiros 15 registros. A terceira e última forma, utilizada para dividir os registros em páginas, passando como parâmetro a classe que mapeia a tabela a ser lista, a página a ser trazida e a quantidade de registros que a página deve conter.

Voltar

4.5. QueryBuilder


Para criar consultas, desde as simples até as complexas, o desenvolvedor pode optar por usar o QueryBuilder.

Voltar

4.5.1. Obtendo o QueryBuilder


Para obter uma instância, basta que o EntityManager crie uma, da seguinte maneira:

Código Exemplo 25: Exemplo de como obter uma instância do QueryBuilder

<?php
    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $q1 = $orm->createQuery();
    $q2 = $orm->createQuery(App\Models\Empregado::class,'u');
?>

O método createQuery retorna uma instância do QueryBuilder e pode ser utilizado de duas formas, na primeira, basta chamar o método sem passar parâmetro algum e ele irá retornar uma instância sem informação alguma, da segunda maneira, o desenvolvedor pode passar a classe que mapeia a tabela a ser consultada e um alias para a tabela. O alias é um apelido que pode ser atribuído para uma tabela em uma consulta, é normalmente utilizado com reduzir o nome de tabelas e para realizar consultas com Self Join (consultas que fazem ligação de uma tabela com ela mesma).

Voltar

4.5.2. Criando uma consulta simples usando list


Para realizar uma consulta simples, o desenvolvedor pode fazer da seguinte maneira:

Código Exemplo 26: Exemplo de como listar os registro de uma dada tabela usando o QueryBuilder

<?php
    use App\Models\Empregado;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $query = $orm->createQuery();
    $query->from(Empregado::class);
    $emprs = $query->list();
?>

Ou:

Código Exemplo 27: Exemplo de como listar os registro de uma dada tabela usando o QueryBuilder

<?php
    use App\Models\Empregado;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $query = $orm->createQuery(Empregado::class);
    $emprs = $query->list();
?>

Ou ainda:

Código Exemplo 28: Exemplo de como listar os registro de uma dada tabela usando o QueryBuilder

<?php
    use App\Models\Empregado;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $emprs=$orm->createQuery(Empregado::class)->list();
?>

A consulta ilustrada acima, de acordo com a Código Exemplo 28, irá retornar todos os registros da tabela mapeada pela classe "Empregado" em um array com instâncias da mesma classe, onde cada instância representa um registro da tabela.

Para tabelas que possuem um número muito grande de registros, recomenda-se paginar ou filtrar os registros.

Voltar

4.5.3. Criando uma consulta simples usando one


Além do método list o QueryBuilder possui o método one, que nesse caso, retorna apenas um registro mapeado em uma instância da classe indicada no método from. Por exemplo:

Código Exemplo 29: Exemplo de como carregar um registro de uma dada tabela usando o QueryBuilder

<?php
    use App\Models\Empregado;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $empr = $orm->createQuery(Empregado::class)->one();
?>

A consulta acima, de acordo com a Código Exemplo 29, irá retornar um registro da tabela mapeada pela classe "Empregado", apenas o primeiro registro retornado pela consulta.

Voltar

4.5.4. Join


Para realizar uma consulta com múltiplas tabelas, o desenvolvedor pode fazer da seguinte maneira:

Código Exemplo 30: Exemplo de como realizar uma consulta com múltiplas tabelas

<?php
    use App\Models\Empregado;
    use App\Models\Projeto;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $query = $orm->createQuery();
    $query->from(Empregado::class, 'e');
    $query->join(Projeto::class, 'p');
    $emprs = $query->list();
?>

A consulta acima, de acordo com a Código Exemplo 30, será executada com as tabelas mapeadas pelas classes "Empregado" e "Projeto". O resultado será todos os registros da tabela mapeada pela classe "Empregado" (informado no método from) em um array com instâncias da mesma classe, onde cada instância representa um registro da tabela.

O método join pode ser chamado quantas vezes forem necessárias, porém, o desenvolvedor deve ter em mente que, quanto mais tabelas forem adicionadas à consulta, mais a consulta ficará pesada para ser executada.

Para fazer uma consulta usando o chamado Outer Join, o desenvolvedor pode passar como terceiro parâmetro o tipo de join (left join ou right join) que deve ser usado, por exemplo, para realizar um left join:   Código Exemplo 31: Exemplo de como realizar uma consulta com múltiplas tabelas usando OUTER JOIN

<?php
    use App\Models\Empregado;
    use App\Models\Projeto;
    use ORM\Contants\JoinTypes;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $query = $orm->createQuery();
    $query->from(Empregado::class, 'e');
    $query->join(Projeto::class, 'p', JoinTypes::LEFT);

    $emprs = $query->list();
?>

Caso o tipo de join não for informado, o valor padrão assumido é INNER.

Observação: o método join não implica que a tabela informada como parâmetro nesse método será carregada juntamente com a tabela informada como parâmetro no método from. Essa ação é conhecida como Eager Load, porém o ORM atualmente suporta apenas Lazy Load, ou seja, os registros dos relacionamentos serão carregados somente quando necessário (sob demanda).

Voltar

4.5.5. Where


Para realizar uma consulta com utilizando filtro, o desenvolvedor pode fazer da seguinte maneira:   Código Exemplo 32: Exemplo de como realizar consultas com filtros

<?php
    use App\Models\Empregado;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $query = $orm->createQuery(Empregado::class, 'e');
    $query->where('e.nome')->equals('João da Silva');
    $emprs = $query->list();
?>

A consulta acima, de acordo com a Código Exemplo 32, irá retornar um array contendo todos os registros da tabela mapeada pela classe "Empregado" cuja coluna "nome" possua o valor "João da Silva".

Utilizar mais de um filtro, pode ser feito através do método and ou or:

Código Exemplo 33: Exemplo de como realizar consultas com filtros

<?php
    use App\Models\Empregado;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $query = $orm->createQuery(Empregado::class, 'e');
    $query->where('e.nome')->equals('João da Silva');
    $query->or('e.nome')->equals('Predo da Silva');
    $query->and('e.dataNasc')->equals(new DateTime('1990-05-23'));
    $emprs = $query->list();
?>

A consulta acima, de acordo com a Código Exemplo 33, irá retornar um array contendo todos os registros da tabela mapeada pela classe "Empregado" cuja coluna "nome" possua o valor "João da Silva" ou o valor "Pedro da Silva" e a coluna "dataNasc" seja igual à data "23/05/2018".

Para realizar uma consulta com filtro e múltiplas tabelas, o desenvolvedor pode fazer da seguinte maneira:

Código Exemplo 34: Exemplo de como realizar consultas com filtros e multiplas tabelas

<?php
    use App\Models\Empregado;
    use App\Models\Projeto;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $query = $orm->createQuery();
    $query->from(Empregado::class, 'e');
    $query->join(Projeto::class, 'p');
    $query->where('e.nome')->equals('João da Silva');
    $query->and('p.nome')->equals('PRJ_OZOB');
    $emprs = $query->list();
?>

A consulta acima, de acordo com a Código Exemplo 34, irá retornar um array contendo todos os registros da tabela mapeada pela classe "Empregado" cuja coluna "nome" possua o valor "João da Silva" e a coluna "nome" da tabela mapeada pela classe "Projeto" possua o valor "PRJ_OZOB".

Os métodos where, and e or esperam receber por parâmetro um texto que indica o alias utilizado pela classe e qual atributo da classe deve ser utilizado para o filtro. O retorno desses métodos é um objeto que contém todas as operações de comparação que podem ser utilizados no filtro.   As operações permitidas são:

Operação Parâmetros Atalho Descrição
equals $valor eq Compara se os valores são iguais
notEquals $valor neq Compara se os valores são diferentes
isNull - isn Compara se o valor da coluna é nulo
isNotNull - isnn Compara se o valor da coluna não é nulo
between $inicial, $final bt Compara se o valor da coluna está entre o valor $inicial e o valor $final
notBetween $inicial, $final nbt Compara se o valor da coluna não está entre o valor $inicial e o valor $final
greaterThan $valor gt Compara se o valor da coluna é maior do que o $valor
greaterOrEqualsThan $valor goet Compara se o valor da coluna é maior ou igual ao $valor
lessThan $valor lt Compara se o valor da coluna é menor do que o $valor
lessOrEqualsThan $valor loet Compara se o valor da coluna é menor ou igual ao $valor
in Array $valores - Compara se o valor da coluna está dentro dos $valores do array
notIn Array $valores - Compara se o valor da coluna não está dentro dos $valores do array
like $valor lk Compara o valor da coluna é compatível com $valor informado. O valor informado pode utilizar o "%" como coringa em qualquer posição, por exemplo, no começo do $valor "%da Silva" indica que o valor da coluna deve terminar com o trecho "da Silva"
notLike $valor nlk Compara o valor da coluna não é compatível com $valor informado. O valor informado pode utilizar o "%" como coringa em qualquer posição, por exemplo, no começo do $valor "%da Silva" indica que o valor da coluna deve terminar com o trecho "da Silva"
contains $valor ctn Compara se o $valor está contido no valor da coluna.
notContains $valor nctn Compara se o $valor não está contido no valor da coluna.
beginsWith $valor bwt Compara se o valor da coluna começa com $valor.
notBeginsWith $valor nbwt Compara se o valor da coluna não começa com $valor.
endsWith $valor ewt Compara se o valor da coluna termina com $valor.
notEndsWith $valor newt Compara se o valor da coluna não termina com $valor.

Voltar

4.5.6. Paginação


A paginação é um recurso muito útil para o desenvolvedor, ele permite que os registros sejam divididos em páginas menores para serem listados em tela para o usuário, caso contrário, todos os registros que existem na tabela seriam exibidos de uma só vez.

Isso não parece assim tão mal, porém, em um caso onde a tabela possua milhares ou mesmo centenas de milhares de registros, levaria muito tempo para carregar tudo, ou o sistema iria travar, ou ainda resultaria em erro.

A paginação serve para resolver esse tipo de problema, e pode ser utilizada das seguintes maneiras:

Código Exemplo 35: Exemplo de como realizar consultas com paginação

<?php
    use App\Models\Empregado;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();

    $emprs = $em->list(Empregado::class, 2, 10);
?>

Código Exemplo 36: Exemplo de como realizar consultas com paginação usando QueryBuilder

<?php
    use App\Models\Empregado;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $page = 2;
    $quantity = 10;
    $query = $em->createQuery(Empregado::class);
    $query->page($page, $quantity);
    $emprs = $query->list();
?>

Ambas as consultas realizam uma consulta na tabela mapeada pela classe "Empregado". O ORM irá gerar uma consulta onde ele divide os registros da tabela em páginas, contendo 10 registros por página, então irá retornar um array contendo os registros da segunda página.

Uma maneira alternativa para recuperar a primeira página seria o método top:

Código Exemplo 37: Exemplo de como realizar consultas com paginação usando top

<?php
    use App\Models\Empregado;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $query = $em->createQuery(Empregado::class);
    $query->top(10);
    $emprs = $query->list();
?>

As queries acima, de acordo com a Código Exemplo 37, realizam uma consulta na tabela mapeada pela classe "Empregado" muito semelhante às anteriores. O ORM irá gerar uma consulta onde ele irá retornar um array contendo 10 registros, que seria equivalente à primeira página.

Voltar

4.5.7. OrderBy


O método orderBy define a ordem em que os registros devem ser retornados na consulta.

Código Exemplo 38: Exemplo de como realizar consultas ordenadas

<?php
    use App\Models\Empregado;
    use ORM\Constants\OrderTypes;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();
    $query = $em->createQuery(Empregado::class);
    $query->orderBy('e.dataNasc', OrderTypes::DESC);
    $query->orderBy('e.nome', OrderTypes::ASC);
    $emprs = $query->list();
?>

A consulta acima, de acordo com a Código Exemplo 38, irá retornar todos os registros da tabela mapeada pela classe "Empregado" em um array com instâncias da mesma classe, onde cada instância representa um registro da tabela, ordenados pelas colunas "dataNasc" em ordem decrescente e "nome" em ordem crescente.

O método orderBy é acumulativo, pode ser chamado quantas vezes forem necessárias. Caso o segundo parâmetro não for informado, o ORM irá usar a ordem padrão que é ASC (ascendente).

Voltar

4.5.8. GroupBy


O método groupBy define um agrupamento para criar relatórios e totalizações separados em grupos. A instrução de agrupamento é frequentemente usada com funções de agregação para agrupar o conjunto de resultados em uma ou mais colunas.   Código Exemplo 39: Exemplo de como realizar consultas agrupadas

<?php
    use App\Models\Empregado;
    use ORM\Constants\OrderTypes;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();

    $query = $em->createQuery(Empregado::class);
    $query->count('e.id', 'total');
    $query->groupBy('e.dataNasc');
    $emprs = $query->list();
?>

A consulta acima, de acordo com a Código Exemplo 39, irá retornar em um array contendo o resultado da consulta, onde cada entrada do resultado é um array que possui os campos "total" e "dataNasc". O valor de "total" representa uma contagem de quantos "Empregados" nasceram no mesmo dia representado pelo valor de "dataNasc".

O método groupBy pode receber por parâmetro quantos parâmetros forem necessários, um após o outro, na mesma chamada do método.

Voltar

4.5.9. Agregação


Uma função de agregação executa um cálculo em um conjunto de valores e retorna um único valor. As funções de agregação frequentemente são usadas com a cláusula GROUP BY em uma consulta.   Código Exemplo 40: Exemplo de como realizar consultas com funcões de agregação

<?php
    use App\Models\Empregado;
    use ORM\Constants\OrderTypes;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();

    $query = $em->createQuery(Empregado::class);
    $query->count('e.id', 'total');
    $query->max('e.salario', 'maiorSalario');
    $query->groupBy('e.dataNasc');

    $emprs = $query->list();
?>

A consulta acima, de acordo com a Código Exemplo 40, irá retornar em um array contendo o resultado da consulta, onde cada entrada do resultado é um array que possui os campos "total", "maiorSalario" e "dataNasc". O valor de "total" representa uma contagem de quantos "Empregados" nasceram no mesmo dia representado pelo valor de "dataNasc", e o valor de "maiorSalario" representa o maior salário que um "Empregado", que nasceu nesse dia, recebe.

O segundo parâmetro do método de agregação, por exemplo, o total, é um alias que o desenvolvedor pode atribuir para o campo para facilitar na utilização do mesmo.

As funções de agregação permitidas são:

Operação Parâmetros Descrição
avg $coluna, $alias Calcula a média dos valores da $coluna
sum $coluna, $alias Calcula a soma dos valores da $coluna
min $coluna, $alias Retorna o menor valor da $coluna
max $coluna, $alias Retorna o maior valor da $coluna
count $coluna, $alias Calcula a quantidade dos valores da $coluna

Voltar

4.5.10. Having


O método having especifica um critério de filtro utilizando uma função de agregação, pois a clausula where não consegue realizar esse tipo de filtro. Na maioria dos bancos de dados, é obrigatório usado com a cláusula GROUP BY antes de usar o having.

Código Exemplo 41: Exemplo de como realizar consultas com having

<?php
    use App\Models\Empregado;

    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();

    $query = $em->createQuery(Empregado::class);
    $query->groupBy('e.dataNasc');
    $query->having()
        ->avg('e.salario')->gt(5000)->and()
        ->count('e.id')->gt(5);
    $emprs = $query->list();
?>

A consulta acima, de acordo com a Código Exemplo 41, irá retornar uma lista contendo a "dataNasc" da tabela mapeada pela classe "Empregado", filtrando pelos registros cujo salário seja maior do que a média, e que a quantidade de registros agrupados pela data seja maior do que 5.

As funções de agregação são as mesmas das descritas na seção 4.5.10 Having e os métodos de comparação são os mesmos dos descritos na seção 4.5.5 Where com exceção dos métodos: in, notIn, like, notLike, contains, notContains, beginsWith,_ notBeginsWith_, endsWith, notEndsWith.

Voltar

4.6. Save


O método save é utilizado para cadastrar ou alterar um registro no banco de dados. Caso o registro já exista e a chave primária esteja preenchida, o método save irá atualizar o registro existente no banco de dados, caso contrário, um novo registro será adicionado ao banco.

Código Exemplo 42: Exemplo de como utilizar o método save para incluir registro

<?php
    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();

    try {
        $empregado = new App\Models\Empregado();
        $empregado->nome = 'João da Silva';
        $empregado->dataNasc = new DateTime('1990-05-23');

        $em->beginTransaction();
        $empregadoNovo = $em->save($empregado);
        $em->commit();
    } catch(Exception $ex) {
        $em->rollback();
    }
?>

O exemplo acima, de acordo com a Código Exemplo 42, irá resultar em um novo registro na tabela "empregado". O método save irá retornar o novo registro.

Código Exemplo 43: Exemplo de como utilizar o método save para alterar registro

<?php
    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();

    try {
        $empr = $em->find(App\Models\Empregado::class, 1);
        $empr->nome = 'Pedro da Silva';

        $em->beginTransaction();
        $emprAtualizado = $em->save($empr);
        $em->commit();
    } catch(Exception $ex) {
        $em->rollback();
    }
?>

O exemplo acima, de acordo com a Código Exemplo 43, irá atualizar um registro já existente na tabela "empregado" com a chave primária de valor "1". O método save irá retornar o registro atualizado.

Voltar

4.7. Remove


O método remove é utilizado para deletar um registro no banco de dados, caso o mesmo exista.

Código Exemplo 44: Exemplo de como utilizar o método remove para deletar registro

<?php
    $orm = ORM\Orm::getInstance();
    $orm->setConnection('exemplo-mysql');
    $em = $orm->createEntityManager();

    try {
        $empr = $em->find(App\Models\Empregado::class, 1);

        $em->beginTransaction();
        $linhas = $em->remove($empr);
        $em->commit();
    } catch(Exception $ex) {
        $em->rollback();
    }
?>

O exemplo acima, de acordo com a Código Exemplo 44, irá remover um registro já existente na tabela "empregado" com a chave primária de valor "1". O método remove irá devolver a quantidade de linhas afetadas com essa operação.

Voltar

5. LOGGER

É possível definir um log para que o ORM possa registrar as operações que ele realiza. Através de alguns métodos o desenvolvedor pode configurar o Logger para as suas necessidades.

O método setLogDisable define se o log deve estar ativo ou inativo. Passando false por parâmetro para essa função, o desenvolvedor desabilita o Logger e passando true ele é habilitado novamente.

O método setLogLocation define a localização onde os arquivos do log serão salvos.

O método setLogFilename define o prefixo que será utilizado para criar o nome do arquivo de log.

O método setLogLevel define qual o nível de log o ORM deve registrar, os valores esperados são DEBUG, INFO, WARNING ou ERROR. O valor padrão é ERROR.

O método setLogOccurrency define com qual frequência o Logger deve criar um novo arquivo. Essa configuração impede que os arquivos de log tenham tamanhos grandes demais. Os valores esperados são DAILY ou MONTHLY. O valor padrão é DAILY.

O método getLogger retorna a instância que está sendo utilizada pelo ORM. O Logger do ORM pode ser utilizado em outras partes da aplicação. Para isso basta usar os métodos debug, info, warning e error para registrar uma entrada no log conforme o nível desejado.

Voltar

6. DRIVER

O desenvolvedor pode criar o próprio Driver para um banco de dados ou uma versão ainda não suportada pelo ORM. O Driver permite que o ORM consiga se comunicar com o banco de dados correspondente, por exemplo, o banco de dados MySQL, possui um Driver correspondente para permitir a comunicação do ORM com este banco de dados.

Para criar um novo Driver, o desenvolvedor precisa atender a algumas regras:

  • Nome do arquivo: o nome do arquivo precisa conter o nome do banco de dados de acordo com o nome esperado pelo PDO (PHP Data Object, é uma interface do PHP para acessar banco de dados), por exemplo, sqlite.php. Caso o Driver seja para uma vesão específica, a versão precisa estar também no nome do arquivo, por exemplo, para a versão 5.11 do banco de dados MySQL, o nome do arquivo seria mysql-5.11.php;
  • Nome da classe: o nome da classe precisa ser equivalente ao nome do arquivo conforme definido acima, por exemplo, para a versão 5.11 do banco de dados MySQL, o nome da classe seria MySQLDriver_5_11. E caso não possua uma versão definida, MySQLDriver. Essa é mais uma sugestão do que uma regra, mas ajuda evitar problemas de classe com nomes iguais;
  • Retonar o nome da classe: o nome da classe precisa ser retornado ao final do arquivo, por exemplo, return MySQLDriver::class; ;
  • Localização do arquivo: o arquivo precisa estar localizado na pasta driver dentro da pasta raiz do ORM, por exemplo, /home/user/app/orm/driver;
  • Precisa estender de ORM\Core\Driver: a classe para o novo Driver precisa extender a classe ORM\Core\Driver, do contrário, o ORM não irá considerar como válido.
  • O novo Driver precisa ser Singleton: a classe precisa seguir o Desing Pattern Singleton para que o ORM use uma instância única do ORM. Caso a classe não seja Singleton, o ORM irá emitir um erro.
  • As configurações do novo Driver: o Driver possui uma série de configurações para que o ORM consiga se comunicar com o banco de dados. Elas devem ser feitas no método construtor da classe. As configurações serão listadas mais à frente.

O Driver possui as seguintes configurações:

  • $GENERATE_ID_TYPE: indica como o banco de dados faz a incrementação do valor da chave primária. Os valores esperados são: ATTR, QUERY ou SEQUENCE;
  • $GENERATE_ID_ATTR: caso o tipo de incrementação seja igual a ATTR, aqui é definida qual é o atributo que o ORM irá usar, por exemplo, AUTO_INCREMENT para o banco de dados MySQL;
  • $GENERATE_ID_QUERY: caso o tipo de incrementação seja igual a QUERY ou SEQUENCE, aqui é definida query que o ORM irá usar para realizar a incrementação do valor da chave primária, por exemplo, select orm_sequence.nextval from dual para o banco de dados Oracle;
  • $SEQUENCE_NAME: define o nome da sequence que o ORM irá criar caso o ORM precise criar as tabelas no banco de dados. O valor padrão é orm_sequence;
  • $IGNORE_ID_DATA_TYPE: caso o valor desse atributo seja true, o ORM irá ignorar o valor definido para a coluna, como pode acontecer, por exemplo, com o banco de dados PostgreSQL;
  • $FK_ENABLE: indica de o ORM deve criar o campo como chave estrangeira. O valor padrão é true;
  • $PAGE_TEMPLATE: define como o banco de dados faz uma consulta paginada, por exemplo, o banco de dados MySQL possui a clausula LIMIT para realiza essa tarefa;
  • $TOP_TEMPLATE: define como o banco de dados faz uma consulta trazendo somente um determinado número de registros, por exemplo, o banco de dados MySQL possui a clausula LIMIT para realiza essa tarefa;
  • $DATA_TYPES: define os tipos de dados aceitos pelo ORM e mapeia para os dados suportados pelo banco de dados. Os tipos recomendados são: string, int, float, lob (Large Object, por exemplo, BLOB ou CLOB), date, time, datetime, bool;
  • $FORMATS: define os formatos que o banco de dados aceita para os tipos date, time e datetime.

A seguir, um exemplo de implementação para uma classe do Driver:

Código Exemplo 45: Exemplo de Driver para o banco de dados MySQL

<?php

use ORM\Contants\GeneratedTypes;
use ORM\Core\Driver;

if (!class_exists('MySQLDriver_5_11')) {

    class MySQLDriver_5_11
    {

        private static $instance;

        const NAME = 'MySQL';

        const VERSION = '5.11';

        private function __construct()
        {
            $this->GENERATE_ID_TYPE = GeneratedTypes::ATTR;
            $this->GENERATE_ID_ATTR = 'AUTO_INCREMENT';
            $this->PAGE_TEMPLATE = "%s \nLIMIT %d, %d";
            $this->TOP_TEMPLATE = "%s \nLIMIT %d";
            $this->DATA_TYPES = [
                'string' => 'VARCHAR(%d)',
                'int' => 'INTEGER',
                'float' => 'DOUBLE',
                'lob' => 'TEXT',
                'date' => 'DATE',
                'time' => 'TIME',
                'datetime' => 'DATETIME',
                'bool' => 'TINYINT(1)',
            ];
        }

        public static function getInstance() : Driver
        {
            if (!self::$instance) {
                self::$instance = new self();
            }

            return self::$instance;
        }

        public function getConnection(Array $config) : \PDO
        {
            $this->validateFields(['db', 'host', 'schema', 'user', 'pass'], $config);
            $dsn = "$config[db]:host=$config[host];dbname=$config[schema]";

            return $this->createConnection($dsn, $config['user'] ?? null, $config['pass'] ?? null);
        }

    }

}

return MySQLDriver_5_11::class;

Voltar

orm's People

Contributors

dfrancklin avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.