Lightning talk apresentada no MeetUp PHPRS subseção Canela/Gramado no dia 26/11/2016 - hotel Klein Ville de Canela (RS):
http://www.meetup.com/pt-BR/PHP-RS/events/234978772/
Evolução e futuro do uso de paradigmas no JavaScript
Doctrine for Dummies
1.
2. Bacharel em Informática com ênfase em Análise de
Sistemas pela Unisinos, cursou mestrado em Engenharia
Informática e de Computadores pelo Instituto Superior
Técnico da Universidade Técnica de Lisboa (Portugal),
perito judicial ad hoc especializado em TI (mantenedor do
site PERITO.inf.br), Zend Certified Engineer (PHP 5.3), Zend
Certified PHP Engineer (PHP 5.5) e Zend Framework 2
Certified Architect (ZFCA) #ZEND004019, Certified
ScrumMaster pela Scrum Alliance #203613, Microsoft
Certified Professional (MCP), idealizador do projeto
Certificamp, consultor web e PHP evangelist.
Ari Stopassola Junior
4. 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/
14. PDO x DBAL
Data-access Layer
• Permite a troca de banco de
dados utlizando 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
15. 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);
}
16. 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
17. 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
18. Doctrine 2 implementa Data Mapper
Fonte: http://martinfowler.com/eaaCatalog/dataMapper.html
21. 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")
*/
28. 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
29. Doctrine Query Language – DQL
$query = EntityManager::createQuery("select p from
VendaBalcaoEntitiesPasseios p where p.preco >= 90
AND p.preco <= 150");
$passeios = $query->getResult();
34. Possível workflow
1) Crie as entidades com suas respectivas annotations
2) Verifique incoerências das classes mediante o BD:
$ vendor/bin/doctrine orm:validate-schema
3) Realize a varredura nas annotations e crie as respectivas tabelas:
$ vendor/bin/doctrine orm:schema-tool:update --force
35. 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;
37. 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
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.
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.
Top 5 contributors do projeto: https://github.com/doctrine/doctrine2/graphs/contributors
Inspirado no Hibernate do Java
E como ficam as agregações, composições de objetos?
O Doctrine é uma coleção de sub-projetos como, por exemplo, DBAL, cache, Annotations etc.
Instala também o Doctrine Commons.
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();
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.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.
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.
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.