2. Bacharel em Informática com ênfase em Análise de Sistemas (Unisinos),
estudou na Universidade Técnica de Lisboa (Portugal), é Zend Certified
Engineer (PHP 5.3), Zend Certified PHP Engineer (PHP 5.5), Rogue
Wave Zend Certified Engineer 2017-PHP (PHP 7.1), Zend Framework 2
Certified Architect (ZFCA), Certified ScrumMaster pela Scrum Alliance,
Microsoft Certified Professional (MCP), idealizador do curso Certificamp,
autor do "Guia Preparatório para a Certificação PHP", consultor web e
PHP evangelist.
Atualmente é discente de pós-graduação em Computação Forense &
Perícia Digital, mantenedor do site www.perito.inf.br e criador do
TopTrumPHPs - SuperTrunfo de frameworks PHP www.toptrumphps.com.
Ari Stopassola Junior
11. Mapeamento Objeto Relacional (ORM)
• Persistir o objeto numa estrutura
de dados relacional
• Tradução para tabelas, campos,
linhas e relacionamentos
• Conversões de tipo
• ORM mascara detalhes obscuros
• Overhead
• Requer aprendizagem de outras
tencnologias. Ex.: DQL (Doctrine),
Propel, Eloquent etc.
http://www.edzynda.com/use-laravels-eloquent-orm-outside-of-laravel/
23. Eloquent implementa Active Record
class Passeios extends Eloquent {
}
$passeio = Passeios::find(32);
$passeio->name = "Tour Uva e Vinho";
$passeio->save();
Fonte: http://www.martinfowler.com/eaaCatalog/activeRecord.html
24. Doctrine 2 implementa Data Mapper
Fonte: http://martinfowler.com/eaaCatalog/dataMapper.html
25. Data Mapper
• Camada de software que separa
objetos em memória do banco de
dados
• Sua responsabilidade é transmitir
dados entre ambos e isolar um do
outro
• Objetos desconhecem o esquema do
banco de dados, tão pouco usam
SQL
https://2013.nosql-matters.org/cgn/index.html%3Fp=2156.html
28. Annotations
• Instruções declarativas dentro de blocos de documentação
• Doctrine usa anotações para definir o mapeamento objeto-
relacional
• Annotations são metadados que descrevem a entidade, como ela
deve ser armazenada, que tipo de colunas serão usadas etc.
• Inspirado no PHPDocumentor www.phpdoc.org
• Definida sempre acima do nome da classe e de cada atributo
• Entre /** xxx */ e começam com o simbolo @
/**
* Produto
*
* @Entity
* @Table(name="produtos")
*/
30. @Column(type="xxxx")
• smallint, integer, bigint
• decimal, float
• string, text, guid
• binary, blob, boolean
• date, date time, datetimez, time
• array, simple_array, json_array, object
http://doctrine-
dbal.readthedocs.io/en/latest/reference/types.html
31. Mapeandos os tipos de dados
Tipos do Doctrine Tipos SQL Tipos PHP
string VARCHAR string
integer INT integer
smallint SMALLINT integer
bigint BIGINT string
boolean BOOLEAN boolean
decimal DECIMAL double
date DATETIME DateTime
time TIME DateTime
datetime DATETIME/TIMESTAMP DateTime
text CLOB string
35. Unit of Work
Fonte: http://martinfowler.com/eaaCatalog/unitOfWork.html
• Estratégia transactional write-behind
• Retarda a execução de cláusulas
SQL para executá-las
posteriormente de forma mais
eficiente
• Executa numa ordem tal de modo a
liberar o mais rápido possível as
tabelas em questão (write locks), ao
fim da transação
43. Workflow
1) Crie as entidades com suas respectivas annotations
2) Implemente o cli-config.php (na raiz do projeto) que chama o
bootstrap.php – de acordo com o exemplo a seguir
3) Realize a varredura nas annotations e crie as respectivas tabelas:
vendor/bin/doctrine orm:schema-tool:create
• Verifique incoerências das classes mediante o BD:
vendor/bin/doctrine orm:validate-schema
• vendor/bin/doctrine orm:schema-tool:update --force
44. <?php
require_once "vendor/autoload.php";
use DoctrineORMToolsSetup;
use DoctrineORMEntityManager;
$config = Setup::createAnnotationMetadataConfiguration(array("./src"));
//Configura a base de dados
$conexao = array(
'driver' => 'pdo_mysql',
'host' => 'localhost',
'dbname' => 'tutorial-doctrine',
'user’ => 'root',
'password' => 'root'
);
//Disponibiliza o EntityManager
$entityManager = EntityManager::create($conexao, $config);
bootstrap.php
45. cli-config.php
<?php
require_once "bootstrap.php";
//Precisamos prover ao entityManager uma interface via linha de comando
//A interface CLI nos permite interagir com o banco de dados como, por exemplo
//criar e atualizar esquemas de BD
return DoctrineORMToolsConsoleConsoleRunner::createHelperSet($entityManager);
56. Relação 1:1 (lê-se um-para-um)
“cada colaborador trabalha para uma empresa parceira”
Colaborador
$id
$parceiro
Parceiro
$id
Owning side Inverse side
/**
* @OneToOne(targetEntity="Parceiro")
* @JoinColumn(name="parceiro", referencedColumnName="id")
*/
protected $parceiro;
57. id nome preco duracao
1 Tour Uva e Vinho 99 12
2 Noite Gaúcha 110 4
3 Alpen Park 30 3
4 Canyon Itaimbezinho 99 10
5 Parques de Gramado 35 5
pacotes_id passeios_id
1 1
1 2
2 3
2 4
3 3
4 1
4 5
Passeios
Relação N:M (ene-para-eme)
“Pacotes têm passeios e o mesmo passeio compõe vários pacotes”
id nome
1 Serra Gaúcha Tradicional
2 Aventura
3 Serra com as Crianças
4 Italiana e Alemã
Pacotes
67. PDO x DBAL
Data-access Layer
• Permite a troca de banco de
dados utilizando as mesmas
chamadas de métodos
• Não reescreve SQL
• Tão pouco emula
funcionalidades inexistentes
Database Abstraction Layer
• Agnóstico
• Manipulação por meio de uma
API Orientada à Objetos
• Traz maior consistência na
manipulação do BD
• Doctrine usa DBAL, mas você
pode usar DBAL sem Doctrine
• DBAL utiliza PDO internamente
68. ExemplodeDBAL
<?php
include __DIR__ . '/doctrine_autoloader.php';
use DoctrineDBALConfiguration;
use DoctrineDBALDriverManager;
//Obtém a conexão
$dbParams = include __DIR__ . '/database.params.php';
$conn = DriverManager::getConnection($dbParams, new Configuration());
$sql = "SELECT * FROM orcamentos WHERE sobrenome = ?";
$stmt = $conn->prepare($sql);
$stmt->execute(array('STOPASSOLA'));
//OU utilizando QueryBuilder
$qb = $conn->createQueryBuilder();
$qb->select('*')->from('orcamentos')->where('sobrenome = :name');
$data = array(':name' => 'STOPASSOLA');
while ($tupla = $stmt->fetch()) {
var_dump($tupla);
}
69. Namespaces
//Cria um novo livro
$livro = new PublicacoesLivro();
$livro->setNome("Guia preparatório para a Certificação PHP");
$livro->setEdicao(1);
//Persiste no banco de dados
$entityManager->persist($livro);
$entityManager->flush();
70. Repository Pattern
//Obtem TODOS os livros com o método findAll
//Obs.: uso do namespace é imprescindível
$livros = $em->getRepository('PublicacoesLivro')->findAll();
echo "<strong>Listando todos os livros</strong><br>";
foreach($livros as $livro){
echo $livro->getNome()."<br>";
}
Instância de
EntityManager Fonte: https://tommcfarlin.com/repository-pattern-benefits/
71. Repository: find()
$livro = $em->getRepository('PublicacoesLivro')->find(1);
echo $livro->getNome();
Busca pelo ID
73. Doctrine Query Language – DQL
$query = EntityManager::createQuery("select p from
VendaBalcaoEntitiesPasseios p where p.preco >= 90
AND p.preco <= 150");
$passeios = $query->getResult();
Inspirado na JSR-317 Hibernate.Não resolve problemas automaticamente.
E como ficam as agregações, composições de objetos?
Relação todo parte.A crítica é exclusiva de um livro, então haverá uma chave estrangeira em Crítica (livro_id, por exemplo).
As partes não são exclusivas do todo. Ex.: Livro (todo) e autor (parte), embora o autor possa ter escrito outros livros. Será necessário criar uma tabela associativa intermediária.
Reduzir a impedância.
Experimente fazer um left outer join num ORM, ou uma função de agregação como média. Alguns falharam ao executar transações, passando a responsabilidade para a aplicação.Não há necessidade de cache, pois o mongoDB já fica em memório – o quanto houver de RAM disponível.Usar monboDB simplifica o desenvolvimento da aplicação pois não requer tratar de atualizações de registros, cache expirado etc.
Conceitualmente objetos formam grafos, enquanto que o banco relacional é tabular.
Hibernate do Java e ao ActiveRecord do Rails. Mapeamento em arquivos .ini ou XMLPropel e Doctrine usam o design pattern ActiveRecord, enquanto que o Zend_Db_Table usa Table Data Gateway pattern e Row Data Gateway pattern.
Livro "Patterns of Enterprise Application Architecture" do Martin Fowler de 2003.CakePHP
Doctrine é a mais popular.
Não serve para estruturas dinâmicas como MongoDB, por exemplo.
https://github.com/doctrine/doctrine2
https://github.com/propelorm/Propel2Quem usa Symfony, automaticamente usa Doctrine.
Suporta também os mais variados sistemas gerenciadores de banco de dados, sejam eles relacionais ou NoSQL.Grupo de bibliotecas orientadas a persistência.
Top 5 contributors do projeto: https://github.com/doctrine/doctrine2/graphs/contributors
Inspirado no Hibernate do Java
O Doctrine é uma coleção de sub-projetos como, por exemplo, DBAL, cache, Annotations etc.
Generating autoload files
Herda toda a lógica de persistência do ORM, gerando overhead.
Pode-se utilizar YAML, XML e o próprio PHP.
Annotations são metadados que descrevem a entidade, como ela deve ser armazenada, tipo de colunas serão usadas etc.
@Entity identifica a classe como uma entidade para o EntityManager@Table informa o nome da tabela, embora seja dispensável caso a tabela tenha o mesmo nome da classe.
@Column identifica uma propriedade do objeto como um campo da tabela. Podem haver outras propriedades que não sejam mapeadas. Se o nome for diferente, usa-se o atributo ”name”. Caso o nome do campo mude na tabela, basta apontar na annotation da respectiva classe
É um componente muito utilizado em outros projetos, além do Doctrine.
Mecanismo que lida com a persistência dos objetos. É a implementação do design pattern ”Data Mapper”Registrar uma entidade.
Mecanismo que lida com a persistência dos objetos.
Executa quando ocorre o flush.
Útil para quem utiliza Testes unitários, onde os testes são feitos encapsulados em uma transação e depois desfeitos no fim – de modo a não alterar o BD.
Cada insert, se único, será encapsulado numa transação.
Mapped Superclasses
TABLE_PER_CLASS
orm:schema-tool:update --dump-sqlmostra a query que deverá ser executada no BD para alinhar com as classes registradas (entidades)
[Database] FAIL - The database schema is not in sync with the current mapping file.
Sem esse arquivo, não conseguimos executar comandos como:
vendor/bin/doctrine orm:validate-schema
vendor/bin/doctrine orm:schema-tool:create
Entities representam o domínio, o problema que está se solucionando. Define-o primeiro, depois defina o DB,
Ocramius: ”o banco serve apenas para guardar coisas”.Após modelar o problema, a solução vem automaticamente (com um pouquinho de esforço, é claro)
Uma e somente uma…@var é uma anotação do DocBlock ignorada pelo Doctrine, utilizada para completar código nas IDEs
Uma e somente uma…
Uma e somente uma…
mappedBy é utilizado apenas no "owning side"
Instala também o Doctrine Commons.PDO abstrai o acesso aos dados e não propriamente o banco de dados, pois não reescreve SQL, tão pouco emula recursos ausentes em determinado BD. Ou seja: diretivas SQL específicas não são traduzidas.
Evita utilizar um ”dialeto” SQL específico de cada banco. Não que necessariamente o BD será trocado o tempo todo, mas traz maior consistência.Esconde detalhes de cada banco.Ex.: PostreSQL
CREATE SEQUENCE serial;SELECT nextval('serial');JSON em BD também é um recurso interessantíssimo do PostgreSQL
Padroniza o acesso via OO.Conexão via DBAL é semelhante ao que seria feito através de PDO. Inclusive os nomes dos métodos são semelhantes, para diminuir a curva de aprendizado.Usa interface fluente. Ex.: $obj->metodoA()->metodoB()->metodoC();
Usa ”fluent interface”, termo cunhado por Eric Evans and Martin Fowler em 2005.
Inspirado do Hibernate do Java (HQL), é um ”dialeto” de SQL orientado à objetos.
Mais controle sobre as querys.Pensar nas consultas sob o ponto de vista de objetos ao invés de relacionamentos.
Ver Expression.
As consultas trazem objetos.