80
Doctrine 2 Camada de Persistência para PHP 5.3+ Guilherme Blanco, Yahoo! sábado, 26 de junho de 2010

Doctrine2 Seminário PHP

Embed Size (px)

Citation preview

Page 1: Doctrine2 Seminário PHP

Doctrine 2

Camada de Persistência para PHP 5.3+

Guilherme Blanco, Yahoo!

sábado, 26 de junho de 2010

Page 2: Doctrine2 Seminário PHP

Quem sou eu?

Web developer a mais de 10 anos

Evangelista Open Source

Trabalha para Yahoo!

Contribui para... ...Doctrine ...Zend Framework ...Symfony ...PHP etc

Gosta de cantar e pescar no tempo livre! =)

sábado, 26 de junho de 2010

Page 3: Doctrine2 Seminário PHP

Quem sou eu?

http://www.twitter.com/guilhermeblanco

http://www.facebook.com/guilhermeblanco

sábado, 26 de junho de 2010

Page 4: Doctrine2 Seminário PHP

Doctrine 2

sábado, 26 de junho de 2010

Page 5: Doctrine2 Seminário PHP

Doctrine 2

PHP 5.3+

100% do código reescrito

Código totalmente em namespaces

sábado, 26 de junho de 2010

Page 6: Doctrine2 Seminário PHP

Doctrine 2

Ferramentas usadas: phpUnit Unit test Phing Pacotes e distribuição Symfony Components

YAMLConsole

Sismo Continuous Integration GIT Controle de versão do código JIRA Gerenciamento de bugs Trac Timeline, código fonte & visualizar alterações

sábado, 26 de junho de 2010

Page 7: Doctrine2 Seminário PHP

Doctrine 2

Três principais pacotes: Common

DBAL

ORM

sábado, 26 de junho de 2010

Page 8: Doctrine2 Seminário PHP

Doctrine\Common

[email protected]:doctrine/common.git

Cache Drivers

sábado, 26 de junho de 2010

Page 9: Doctrine2 Seminário PHP

Doctrine\Common\Cache

Drivers Suportados: APCCache

$cacheDriver = new \Doctrine\Common\Cache\ApcCache();

MemcacheCache$memcache = new \Memcache();$memcache->addServer('memcache_host', 11211);

$cacheDriver = new \Doctrine\Common\Cache\MemcacheCache();$cacheDriver->setMemcache($memcache);

XcacheCache$cacheDriver = new \Doctrine\Common\Cache\XcacheCache();

sábado, 26 de junho de 2010

Page 10: Doctrine2 Seminário PHP

Doctrine\Common\Cache

Cache Drivers Interface:

interface \Doctrine\Common\Cache\Cache {function setNamespace($namespace);function getIds();

function fetch($id);

function contains($id);

function save($id, $data, $lifeTime = 0);

function delete($id);function deleteAll();

function deleteByRegex($regex);function deleteByPrefix($prefix);function deleteBySuffix($suffix);

}

sábado, 26 de junho de 2010

Page 11: Doctrine2 Seminário PHP

Doctrine\Common

[email protected]:doctrine/common.git

Cache Drivers

Class Loader

sábado, 26 de junho de 2010

Page 12: Doctrine2 Seminário PHP

Doctrine\Common\ClassLoader

Implements PSR #0 PSR = PHP Standards Recommendation

Interoperabilidade Técnica entre bibliotecas Symfony, Zend Framework, Doctrine, Agavi, PEAR2/Pyrus,

Lithium, Flow3, Solar, etc

Possível merge no core do PHP: SplClassLoader http://wiki.php.net/rfc/splclassloader

sábado, 26 de junho de 2010

Page 13: Doctrine2 Seminário PHP

Doctrine\Common\ClassLoader

Como usar:

require_once '/path/to/lib/Doctrine/Common/ClassLoader.php';

$doctrineClassLoader = new \Doctrine\Common\ClassLoader( 'Doctrine', '/path/to/lib/Doctrine');

$doctrineClassLoader->register();

sábado, 26 de junho de 2010

Page 14: Doctrine2 Seminário PHP

Doctrine\Common

[email protected]:doctrine/common.git

Cache Drivers

Class Loader

Collections

sábado, 26 de junho de 2010

Page 15: Doctrine2 Seminário PHP

Doctrine\Common\Collections

Solução inspirada na interface java.util.Collection

Array simples em PHP são difíceis de manipular

...mas implementações de array customizadas não são compatíveis com as funções de array_*

Uso intenso de Closures

Implementação SplArray do usuário Onde estão os desenvolvedores do PHP?

sábado, 26 de junho de 2010

Page 16: Doctrine2 Seminário PHP

Doctrine\Common

[email protected]:doctrine/common.git

Cache Drivers

Class Loader

Collections

Lexer

sábado, 26 de junho de 2010

Page 17: Doctrine2 Seminário PHP

Doctrine\Common

[email protected]:doctrine/common.git

Cache Drivers

Class Loader

Collections

Lexer

Annotations Parser

sábado, 26 de junho de 2010

Page 18: Doctrine2 Seminário PHP

Doctrine\Common\Annotations

Suporte à Annotations similar ao Java

Define informações de metadados em classes

Extremamente extensível e reutilizável

Supre uma funcionalidade inexistente no PHP Novamente, onde estão os desenvolvedores do PHP? RFC já escrito: http://wiki.php.net/rfc/annotations

sábado, 26 de junho de 2010

Page 19: Doctrine2 Seminário PHP

Doctrine\Common\AnnotationsAnnotations ::= Annotation {[ "*" ]* [Annotation]}*Annotation ::= "@" AnnotationName ["(" [Values] ")"]AnnotationName ::= QualifiedName | SimpleName | AliasedNameQualifiedName ::= NameSpacePart "\" {NameSpacePart "\"}* SimpleNameAliasedName ::= Alias ":" SimpleNameNameSpacePart ::= identifierSimpleName ::= identifierAlias ::= identifierValues ::= Array | Value {"," Value}*Value ::= PlainValue | FieldAssignmentPlainValue ::= integer | string | float | boolean | Array | AnnotationFieldAssignment ::= FieldName "=" PlainValueFieldName ::= identifierArray ::= "{" ArrayEntry {"," ArrayEntry}* "}"ArrayEntry ::= Value | KeyValuePairKeyValuePair ::= Key "=" PlainValueKey ::= string | integer

sábado, 26 de junho de 2010

Page 20: Doctrine2 Seminário PHP

Doctrine\Common\Annotations

Criando classes de Annotations:

final class \Doctrine\ORM\Mapping\Entity extends \Doctrine\Common\Annotations\Annotation { public $repositoryClass;}

Usando as Annotations:

namespace MyProject\Entity;

/** * @Entity(repositoryClass="Repository\UserRepository") */class User { // ... }

sábado, 26 de junho de 2010

Page 21: Doctrine2 Seminário PHP

Doctrine\Common\Annotations

Lendo Annotations:

$reader = new \Doctrine\Common\Annotations\AnnotationReader( new \Doctrine\Common\Cache\ArrayCache());$reader->setDefaultAnnotationNamespace( 'Doctrine\ORM\Mapping\\'); $class = new \ReflectionClass('MyProject\Entity\User');$classAnnotations = $reader->getClassAnnotations($class);

echo $classAnnotations['Doctrine\ORM\Mapping\Entity'] ->repositoryClass;

sábado, 26 de junho de 2010

Page 22: Doctrine2 Seminário PHP

Doctrine\Common\Annotationsinterface \Doctrine\Common\Annotations\AnnotationReader { function setDefaultAnnotationNamespace($defaultNamespace);

function setAnnotationNamespaceAlias($namespace, $alias);

function getClassAnnotations(\ReflectionClass $class);

function getClassAnnotation(\ReflectionClass $class, $annot);

function getPropertyAnnotations(\ReflectionProperty $property);

function getPropertyAnnotation( \ReflectionProperty $property, $annot );

function getMethodAnnotations(\ReflectionMethod $method);

function getMethodAnnotation(\ReflectionMethod $method, $annot);}

sábado, 26 de junho de 2010

Page 23: Doctrine2 Seminário PHP

Doctrine\DBAL

[email protected]:doctrine/dbal.git

DataBase Abstraction Layer construído sobre a PDO e drivers proprietários

Drivers suportados: DB2 Microsoft SQL Server (pdo_sqlsrv & sqlsrv) MySQL PostgreSQL Oracle SQLite

sábado, 26 de junho de 2010

Page 24: Doctrine2 Seminário PHP

Doctrine\DBAL

API para introspecção e gerenciamento de schemas de Bancos de Dados melhorado

Pode se tornar um padrão para DBAL em PHP 5.3 no futuro, tal como MDB2 para PEAR1

Inspirado em ezcDatabase, MDB2 e Zend_Db

Talvez podemos fazer acontecer para a PEAR2

sábado, 26 de junho de 2010

Page 25: Doctrine2 Seminário PHP

Doctrine\DBALinterface \Doctrine\DBAL\Connection { // API para manipulação de dados

/* Executa um SQL DELETE statement numa tabela. */ function delete($tableName, array $identifier);

/* Executa um SQL UPDATE statement numa tabela. */ function update($tableName, array $data, array $identifier);

/* Insere uma linha na tabela com os dados especificados. */ function insert($tableName, array $data);

/* Prepara um SQL statement. Retorna um DBAL\Statement */ function prepare($statement);

/* Aplica um SQL statement e retorna # linhas afetadas. */ function exec($statement);

// ...

sábado, 26 de junho de 2010

Page 26: Doctrine2 Seminário PHP

Doctrine\DBAL // API para Transação

/* Retorna o nível de profundidade da transação corrente. */ function getTransactionNestingLevel();

/* Executa uma função em uma transação. */ function transactional(\Closure $func);

/* Inicia uma transação suspendendo o modo auto-commit. */ function beginTransaction();

/* Aplica a transação corrente. */ function commit();

/* Cancela qualquer alteração na base da transação corrente. */ function rollback();

/* Checa se a transação corrente é marcada como somente rollback. */ function isRollbackOnly();

// ...

sábado, 26 de junho de 2010

Page 27: Doctrine2 Seminário PHP

Doctrine\DBAL // API para obtenção de dados

/* Executa consulta SQL e retorna a 1a. linha num array assoc. */ function fetchAssoc($statement, array $params = array());

/* Executa consulta SQL e retorna a 1a. linha num array numérico. */ function fetchArray($statement, array $params = array());

/* Executa consulta SQL e retorna o valor da 1a. coluna. */ function fetchColumn( $statement, array $params = array(), $colnum = 0 );

/* Executa consulta SQL e retorna todo resultado num array assoc. */ function fetchAll($sql, array $params = array());}

sábado, 26 de junho de 2010

Page 28: Doctrine2 Seminário PHP

Doctrine\DBAL\Types

Ponto centralizado para conversão de tipos Do Banco de Dados para PHP Do PHP para o Banco de Dados

Independente do Banco de Dados

Acesso ao dialeto específico da Base via Platforma

Extensível

sábado, 26 de junho de 2010

Page 29: Doctrine2 Seminário PHP

Doctrine\DBAL\Types

Novo tipo é só implementar uma classe abstrata:interface \Doctrine\DBAL\Types\Type { function convertToDatabaseValue( $value, AbstractPlatform $platform );

function convertToPHPValue( $value, AbstractPlatform $platform );

function getSqlDeclaration( array $fieldDeclaration, AbstractPlatform $platform ); function getName();

function getBindingType();}

sábado, 26 de junho de 2010

Page 30: Doctrine2 Seminário PHP

Doctrine\DBALclass \MyProject\DataTypes\MyObjectType extends \Doctrine\DBAL\Types\Type{ public function getSqlDeclaration( array $fieldDeclaration, AbstractPlatform $platform ) { return $platform->getClobTypeDeclarationSQL($fieldDeclaration); }

public function convertToDatabaseValue( $value, AbstractPlatform $platform ) { return serialize($value); }

public function convertToPHPValue($value, AbstractPlatform $platform) { $value = (is_resource($value)) ? stream_get_contents($value) : $value; return unserialize($value); }

public function getName() { return "my-object"; }}

sábado, 26 de junho de 2010

Page 31: Doctrine2 Seminário PHP

Doctrine\DBAL\Types

Finalmente, faça o Doctrine saber sobre seu tipo:\Doctrine\DBAL\Types\Type::addType( "my-object", "\MyProject\DataTypes\MyObjectType");

Então você pode usar nas suas Entidades!/** * @Entity * @Table(name="files") */class File { // ...

/** * @Column(type="my-object") */ protected $content;}

sábado, 26 de junho de 2010

Page 32: Doctrine2 Seminário PHP

Doctrine\DBAL

Criando um schema:$platform = $em->getConnection()->getDatabasePlatform();

$schema = new \Doctrine\DBAL\Schema\Schema(); $table = $schema->createTable("users"); $table->addColumn("id", "integer", array("unsigned" => true));$table->addColumn("name", "string", array("length" => 32));$table->setPrimaryKey(array("id"));

// obtenha as consultas para criar este schema.$queries = $schema->toSql($platform);

Array( 0 => 'CREATE TABLE users ( id INTEGER NOT NULL, name VARCHAR(32) NOT NULL, PRIMARY KEY("id") )')

sábado, 26 de junho de 2010

Page 33: Doctrine2 Seminário PHP

Doctrine\DBAL

Removendo um schema:// obtém as queries para remover o schema em segurança.$queries = $schema->toDropSql($platform);

Array( 0 => 'DROP TABLE users')

Faz o inverso que ->toSql() faz

sábado, 26 de junho de 2010

Page 34: Doctrine2 Seminário PHP

Doctrine\DBAL

Comparando schemas:$platform = $em->getConnection()->getDatabasePlatform();

$fromSchema = new \Doctrine\DBAL\Schema\Schema();$table = $fromSchema->createTable("users"); $table->addColumn("id", "integer", array("unsigned" => true));$table->addColumn("name", "string", array("length" => 32));$table->setPrimaryKey(array("id"));

sábado, 26 de junho de 2010

Page 35: Doctrine2 Seminário PHP

Doctrine\DBAL

Comparando schemas:$platform = $em->getConnection()->getDatabasePlatform();

$toSchema = new \Doctrine\DBAL\Schema\Schema(); $table = $toSchema->createTable("users"); $table->addColumn("id", "integer", array("unsigned" => true));$table->addColumn("name", "string", array("length" => 32));$table->addColumn("email", "string", array("length" => 255));$table->setPrimaryKey(array("id"));

sábado, 26 de junho de 2010

Page 36: Doctrine2 Seminário PHP

Doctrine\DBAL

Comparando schemas:$platform = $em->getConnection()->getDatabasePlatform();

$comparator = new \Doctrine\DBAL\Schema\Comparator(); $schemaDiff = $comparator->compare($fromSchema, $toSchema);

// queries para alterar de um schema para outro.$queries = $schemaDiff->toSql($platform);

Array( 0 => 'ALTER TABLE users ADD email VARCHAR(255) NOT NULL')

sábado, 26 de junho de 2010

Page 37: Doctrine2 Seminário PHP

Performance em Inserções

Inserindo 20 entradas com Doctrine 2:for ($i = 0; $i < 20; $i++) { $user = new User(); $user->name = 'Guilherme Blanco'; $em->persist($user);}

$start = microtime(0);$em->flush();$end = microtime(0);

echo $end - $start;

sábado, 26 de junho de 2010

Page 38: Doctrine2 Seminário PHP

Performance em Inserções

Inserindo 20 entradas com código PHP “crú”:$start = microtime(0);

for ($i = 0; $i < 20; $i++) { mysql_query( "INSERT INTO users (name) VALUES ('Guilherme Blanco')", $db_link );}

$end = microtime(0);

echo $end - $start;

sábado, 26 de junho de 2010

Page 39: Doctrine2 Seminário PHP

Performance em Inserções

Sem palhaçada aqui! =PQual deles vocês acham que é mais rápido? Doctrine 2

Tempo: 0.0094 segundos Código PHP

Tempo: 0.0165 segundos

PQP?!?! Doctrine + rápido que código PHP puro? Provê muito menos, não provê recursos, sem abstração! A resposta é TRANSAÇÃO!

Doctrine 2 gerencia nossas transações e executa todos os comandos de forma eficiente numa única.

sábado, 26 de junho de 2010

Page 40: Doctrine2 Seminário PHP

Performance em Inserções

Doctrine 2 *NÃO É* mais rápido que código PHP puro

Desenvolvedores passam por cima de pequenos detalhes e podem causar problemas significantes de performance!

sábado, 26 de junho de 2010

Page 41: Doctrine2 Seminário PHP

Performance em Inserções

Inserindo 20 entradas com código PHP “crú”:$start = microtime(0);

mysql_query("START TRANSACTION", $db_link);

for ($i = 0; $i < 20; $i++) { mysql_query( "INSERT INTO users (name) VALUES ('Guilherme Blanco')", $db_link );}

mysql_query("COMMIT", $db_link);

$end = microtime(0);

echo $end - $start;

sábado, 26 de junho de 2010

Page 42: Doctrine2 Seminário PHP

Performance em Inserções

Informações finais de performance... Doctrine 2

Tempo: 0.0094 segundos Código PHP

Tempo: 0.0165 segundos Código PHP (revisitado)

Tempo: 0.0028 segundos

Você pode ler mais sobre isto no blog do Doctrine http://www.doctrine-project.org/blog/transactions-and-performance

sábado, 26 de junho de 2010

Page 43: Doctrine2 Seminário PHP

Doctrine\ORM

O que aprendemos com Doctrine 1? Camada de Persistência != Modelo de Domínio Foco no propósito chave, a Camada de Persistência “You’re doing it wrong!” Extingüir a mágica

sábado, 26 de junho de 2010

Page 44: Doctrine2 Seminário PHP

Doctrine\ORM

Comparação de performance Hidratar 5000 registros

Doctrine 1.2: 4.3 segundos Doctrine 2.0-DEV: 1.4 segundos

Hidratar 10000 registros Doctrine 2.0-DEV: 3.5 segundos

Duas vezes mais registros e ainda assim mais rápido que o Doctrine 1!

sábado, 26 de junho de 2010

Page 45: Doctrine2 Seminário PHP

Doctrine\ORM

Por que é mais rápido? Otimizações do PHP 5.3!

30% menos recursos, 20% mais rápido 5.3-DEV (lazy bucket alloc, interned strings, runtime cache),

Doctrine 2 pode rodar 50% mais rápido! Melhor algoritmo de hidratação Ordenação Topológica Entidades enxutas Aspectos mágicos do Doctrine 1 extintos

sábado, 26 de junho de 2010

Page 46: Doctrine2 Seminário PHP

Doctrine\ORM

Por que extingüir a mágica? Eliminar o fator PQP/minuto

Difícil de debugar Casos extremos são difíceis de corrigir Casos extremos são difíceis de se contornar

Tudo funciona até você sair fora da caixa

...e a mágina é lenta! Eu posso provar, olha! __set é ~87% mais lento que um set normal __get é ~150% mais lento que um get normal

sábado, 26 de junho de 2010

Page 47: Doctrine2 Seminário PHP

Doctrine\ORM

Como extingüir a mágica? Nós chamamos de POO!

Composição Herança Agregação Polimorfismo Encapsulamento etc

sábado, 26 de junho de 2010

Page 48: Doctrine2 Seminário PHP

Doctrine\ORM

DataMapper ao invés de ActiveRecord

Densamente inspirado em JSR-317/JPA v2.0

Java... QUÊ?!?! #$@&*! PHP ainda peca pela falta de padronização PHP Standards Group pode nos socorrer?!

Versão final 2.0.0 esperada para Setembro

sábado, 26 de junho de 2010

Page 49: Doctrine2 Seminário PHP

Doctrine\ORM

Entidades Classe PHP regular Objeto persistente de domínio enxuto Não necessita extender uma classe base! Não pode ser final ou conter métodos final Duas entidades na hierarquia de classes não pode

mapear uma propriedade com o mesmo nome Classes concretas e abstratas podem ser Entidades Entidades podem extender classes não-entidades bem

como classes entidades Classes não-entidade podem extender classes entidades

sábado, 26 de junho de 2010

Page 50: Doctrine2 Seminário PHP

Doctrine\ORMnamespace Entity;

/** * @Entity * @Table(name="users") */class User { /** * @Id @GeneratedValue * @Column(type="integer") */ protected $id;

/** * @Column(type="string", length=32) */ protected $name;

// ... getters and setters}

sábado, 26 de junho de 2010

Page 51: Doctrine2 Seminário PHP

Doctrine\ORMEntity\User: type: entity table: users id: id: type: integer generator: strategy: AUTO fields: name: type: string length: 32

sábado, 26 de junho de 2010

Page 52: Doctrine2 Seminário PHP

Doctrine\ORM<?xml version="1.0" encoding="UTF-8"?><doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mappinghttp://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="Entity\User" table="users"> <id name="id" type="integer"> <generator strategy="AUTO"/> </id> <field name="name" type="string" length="50"/> </entity></doctrine-mapping>

sábado, 26 de junho de 2010

Page 53: Doctrine2 Seminário PHP

Doctrine\ORM

Mapeamento de Colunas type length scale, precision nullable unique name (DB) options columnDefinition

/** * @Column(type="string", length=32, unique=true) */protected $foo;

sábado, 26 de junho de 2010

Page 54: Doctrine2 Seminário PHP

Doctrine\ORM

Campos identificadores Suporta diferentes estratégias:

AUTO SEQUENCE TABLE NONE

/** * @Id @GeneratedValue(strategy="AUTO") * @Column(type="integer") */protected $id;

sábado, 26 de junho de 2010

Page 55: Doctrine2 Seminário PHP

Doctrine\ORM

Campos de associação OneToOne

/** @OneToOne(targetEntity="Shipping") */private $shipping;

OneToMany ManyToOne ManyToMany

/** * @ManyToMany(targetEntity="Group") * @JoinTable(name="users_groups", joinColumns={ * @JoinColumn(name="user_id", referencedColumnName="id") * }, inverseJoinColumns={ * @JoinColumn(name="group_id", referencedColumnName="id") * }) */private $groups;

sábado, 26 de junho de 2010

Page 56: Doctrine2 Seminário PHP

Doctrine\ORM

Herança Concrete Table Inheritance

Sem colunas irrelevantes Sem problemas de colisão

Difícil para lidar com chaves primárias Pesquisa na superclasse significa pesquisar em todas as

tabelas (muitas queries ou umjoin maluco) Refatoração nos campos significa um update em algumas ou

todas as tabelas

sábado, 26 de junho de 2010

Page 57: Doctrine2 Seminário PHP

Doctrine\ORM/** @MappedSuperclass */class MappedSuperclassBase { /** @Column(type="string") */ protected $mapped;

/** * @OneToOne(targetEntity="MappedSuperclassRelated") * @JoinColumn(name="related_id", referencedColumnName="id") */ protected $related;}

/** @Entity @Table(name="users") */class User extends MappedSuperclassBase { /** @Id @Column(type="integer") */ protected $id;

/** @Column(type="string", length=32) */ protected $name;}

sábado, 26 de junho de 2010

Page 58: Doctrine2 Seminário PHP

Doctrine\ORMCREATE TABLE users ( mapped TEXT NOT NULL, id INTEGER NOT NULL, name TEXT NOT NULL, related_id INTEGER DEFAULT NULL, PRIMARY KEY(id));

sábado, 26 de junho de 2010

Page 59: Doctrine2 Seminário PHP

Doctrine\ORM

Herança Single Table Inheritance

Somente uma tabela na base de dados Sem joins Refatoração de campos não muda o schema da tabela

Disperdício de espaço na base de dados Muitos locks devido aos inúmeros acessos Sem duplicação de nome de campos com diferentes significados

sábado, 26 de junho de 2010

Page 60: Doctrine2 Seminário PHP

Doctrine\ORMnamespace MyProject\Entity;

/** * @Entity * @InheritanceType("SINGLE_TABLE") * @DiscriminatorColumn(name="discr", type="string") * @DiscriminatorMap({ * "user" = "User", "employee" = "Employee" * }) */class User { // ...}

/** @Entity */class Employee extends User { // ...}

sábado, 26 de junho de 2010

Page 61: Doctrine2 Seminário PHP

Doctrine\ORM

Herança Class Table Inheritance

Fácil de entender Espaço na tabela é otimizado devido à normalização Relacionamento direto entre o Modelo de Domínio e a base

Muitos joins Refatoração de campos precisa de um update no schema Tabela supertipo é muito acessado, pode estar em lock

sábado, 26 de junho de 2010

Page 62: Doctrine2 Seminário PHP

Doctrine\ORMnamespace MyProject\Entity;

/** * @Entity * @InheritanceType("JOINED") * @DiscriminatorColumn(name="discr", type="string") * @DiscriminatorMap({ * "user" = "User", "employee" = "Employee" * }) */class User { // ...}

/** @Entity */class Employee extends User { // ...}

sábado, 26 de junho de 2010

Page 63: Doctrine2 Seminário PHP

Doctrine\ORM

Proxies Carga-tardia dos dados da Entidade Provê a possibilidade de obter uma referência à

Entidade sem acesso à base de dados Pode ser gerado em tempo de execução ou via

ferramenta de linha de comando

$proxyUser = $em->getReference("User", 1);

sábado, 26 de junho de 2010

Page 64: Doctrine2 Seminário PHP

Doctrine\ORM

EntityManager Ponto central da funcionalidade ORM Aplica a estratégia de Transaction Write Behind que

atrasa a execução de comandos SQL ...isto significa, eficiência! ...e também significa que os locks de escrita são

rapidamente liberados!

Internamante, ele usa UnitOfWork para manter informações de estado dos objetos

sábado, 26 de junho de 2010

Page 65: Doctrine2 Seminário PHP

Doctrine\ORMinterface \Doctrine\ORM\EntityManager { // Transaction API

/* Starts a transaction on the underlying database connection. */ function beginTransaction();

/* Commits a transaction on underlying database connection. */ function commit();

/* Flushes all changes to queued objects to the database. */ function flush();

/* Performs a rollback on the underlying database connection. */ function rollback();

/* Executes a function in a transaction. */ function transactional(\Closure $func);

// ...

sábado, 26 de junho de 2010

Page 66: Doctrine2 Seminário PHP

Doctrine\ORM // Query API

/* Creates a new Query object. */ function createQuery($dql);

/* Creates a native SQL query. */ function createNativeQuery( $sql, \Doctrine\ORM\Query\ResultSetMapping $rsm );

/* Create a QueryBuilder instance. */ function createQueryBuilder();

/* Finds an Entity by its identifier. */ function find($entityName, $identifier, $lockMode = LockMode::NONE, $lockVersion = null);

/* Gets a reference to the entity identified by the given type and identifier without actually loading it. */ function getReference($entityName, $identifier);

// ...sábado, 26 de junho de 2010

Page 67: Doctrine2 Seminário PHP

Doctrine\ORM // Object Manipulation API

/* Tells EntityManager to make instance managed and persistent. */ function persist($entity);

/* Removes an entity instance. */ function remove($entity);

/* Refresh state of entity from database, overrides changes. */ function refresh($entity);

/* Detaches an entity from the EntityManager. */ function detach($entity);

/* Merges state of detached entity into persistence context. */ function merge($entity);

// ...

sábado, 26 de junho de 2010

Page 68: Doctrine2 Seminário PHP

Doctrine\ORM // Repository, Configuration, EventManager, etc

/* Gets the EventManager used by the EntityManager. */ function getEventManager();

/* Gets the Configuration used by the EntityManager. */ function getConfiguration();

/* Gets the repository for an entity class. */ function getRepository($entityName);

/* Returns the metadata for a class. */ function getClassMetadata($className);

/* Gets database connection object used by the EntityManager. */ function getConnection();}

sábado, 26 de junho de 2010

Page 69: Doctrine2 Seminário PHP

Doctrine\ORM

Trabalhando com Entidades no EntityManager Criando o EntityManager

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

$config->setMetadataCacheImpl($cacheDriver);$config->setQueryCacheImpl($cacheDriver);

$config->setProxyDir("/path/to/MyProject/Proxies");$config->setProxyNamespace("MyProject\Proxies");

$connectionOptions = array( "driver" => "pdo_sqlite", "path" => "database.sqlite");

// Creating the EntityManager$em = \Doctrine\ORM\EntityManager::create( $connectionOptions, $config);

sábado, 26 de junho de 2010

Page 70: Doctrine2 Seminário PHP

Doctrine\ORM

Trabalhando com Entidades no EntityManager Persistindo Entidades

try { $em->transactional(function ($em) { $user = new \MyProject\Entity\User(); $user->name = "Guilherme Blanco";

$em->persist($user); });} catch (\Exception $e) { // ...}

sábado, 26 de junho de 2010

Page 71: Doctrine2 Seminário PHP

Doctrine\ORM

Trabalhando com Entidades no EntityManager Atualizando Entidades

try { $em->transactional(function ($em) { $user = $em->find("MyProject\Entity\User", 1); $user->name = "Benjamin Eberlei";

$em->persist($user); });} catch (\Exception $e) { // ...}

sábado, 26 de junho de 2010

Page 72: Doctrine2 Seminário PHP

Doctrine\ORM

Trabalhando com Entidades no EntityManager Removendo Entidades

try { $em->transactional(function ($em) { $user = $em->getReference("MyProject\Entity\User", 1); $em->remove($user); });} catch (\Exception $e) { // ...}

sábado, 26 de junho de 2010

Page 73: Doctrine2 Seminário PHP

Doctrine\ORM

Doctrine Query Language (DQL) Implementação de uma OQL Fortemente influenciada por Hibernate QL Top-down recursive descent parser LL(*), construindo

uma árvore de abstração sintática (AST) AST é então usada para gerar SQL dependente

$query = $em->createQuery( "SELECT u FROM MyProject\Entity\User u");$users = $query->execute();

sábado, 26 de junho de 2010

Page 74: Doctrine2 Seminário PHP

Doctrine\ORM

Native Query Possibilita voltar ao poder da SQL sem perder a

habilidade de hidratar seus dados na sua Entidade$rsm = new \Doctrine\ORM\Query\ResultSetMapping();$rsm->addEntityResult("MyProject\Entity\User", "u");$rsm->addFieldResult("u", "id", "id");$rsm->addFieldResult("u", "name", "name");

$query = $em->createNativeQuery( "SELECT id, name FROM users WHERE username = ?", $rsm);$query->setParameter(1, "guilhermeblanco");

$users = $query->getResult();

sábado, 26 de junho de 2010

Page 75: Doctrine2 Seminário PHP

Doctrine\ORM

QueryBuilder Implementação de um Builder Construção e execução são separadas QueryBuilder não pode ser executada; ao invés disso,

obtenha uma instância de Query e execute-a

$qb = $em->createQueryBuilder() ->select("u") ->from("MyProject\Entity\User", "u");$users = $qb->getQuery()->execute();

sábado, 26 de junho de 2010

Page 76: Doctrine2 Seminário PHP

Doctrine\ORM

Doctrine suporta diferentes níveis de cache Metadata cache

$config->setMetadataCacheImpl($cacheDriver);

Query cache$config->setQueryCacheImpl($cacheDriver);

Result cache$config->setResultCacheImpl($cacheDriver);

$query = $em->createQuery( "SELECT u FROM MyProject\Entity\User u");$query->useResultCache(true, 3600, "my_custom_name");

sábado, 26 de junho de 2010

Page 77: Doctrine2 Seminário PHP

Doctrine\ORM

Console Usa o componente Symfony 2 Console Auxilia a desenvolver com Doctrine Tarefas disponíveis em todos os pacotes

$helperSet = $cli->getHelperSet();$helperSet->set( new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper( $em->getConnection() ), 'db');$helperSet->set( new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper( $em ), 'em');

$cli->addCommands(array(...));

sábado, 26 de junho de 2010

Page 78: Doctrine2 Seminário PHP

Doctrine\ORM

Comandos disponíveis: \Doctrine\DBAL\Tools\Console\Command\RunSqlCommand \Doctrine\DBAL\Tools\Console\Command\ImportCommand \Doctrine\ORM\Tools\Console\Command\ClearCache\MetadataCommand \Doctrine\ORM\Tools\Console\Command\ClearCache\ResultCommand \Doctrine\ORM\Tools\Console\Command\ClearCache\QueryCommand \Doctrine\ORM\Tools\Console\Command\SchemaTool\CreateCommand \Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand \Doctrine\ORM\Tools\Console\Command\SchemaTool\DropCommand \Doctrine\ORM\Tools\Console\Command\ConvertDoctrine1SchemaCommand \Doctrine\ORM\Tools\Console\Command\ConvertMappingCommand \Doctrine\ORM\Tools\Console\Command\GenerateRepositoriesCommand \Doctrine\ORM\Tools\Console\Command\GenerateEntitiesCommand \Doctrine\ORM\Tools\Console\Command\GenerateProxiesCommand \Doctrine\ORM\Tools\Console\Command\EnsureProductionSettingsCommand \Doctrine\ORM\Tools\Console\Command\ValidateSchemaCommand \Doctrine\ORM\Tools\Console\Command\RunDqlCommand

sábado, 26 de junho de 2010

Page 79: Doctrine2 Seminário PHP

Future

DBAL QueryBuilder Concluir o driver MSSQL Server

DQL Suporte a TYPE() Adicionar múltiplos FROM Embedded Values

ODM Extrair a interface de DocumentManager Estabilizar o driver de MongoDB Implementar outros drivers (CouchDB, SimpleDB, ...)

sábado, 26 de junho de 2010

Page 80: Doctrine2 Seminário PHP

Questions?

Guilherme Blanco Informações de contato:

@guilhermeblanco

[email protected]

http://www.facebook.com/guilhermeblanco

+55 16 9215.8480

OBRIGADO PELA PACIÊNCIA!!! =)

sábado, 26 de junho de 2010