Doctrine2 Seminário PHP

  • 6,897 views
Uploaded on

 

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
6,897
On Slideshare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
117
Comments
0
Likes
9

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Guilherme Blanco, Yahoo! Doctrine 2 Camada de Persistência para PHP 5.3+ sábado, 26 de junho de 2010
  • 2. 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
  • 3. Quem sou eu?  http://www.twitter.com/guilhermeblanco  http://www.facebook.com/guilhermeblanco sábado, 26 de junho de 2010
  • 4. Doctrine 2 sábado, 26 de junho de 2010
  • 5. Doctrine 2  PHP 5.3+  100% do código reescrito  Código totalmente em namespaces sábado, 26 de junho de 2010
  • 6. Doctrine 2  Ferramentas usadas:  phpUnit Unit test  Phing Pacotes e distribuição  Symfony Components  YAML  Console  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
  • 7. Doctrine 2  Três principais pacotes:  Common  DBAL  ORM sábado, 26 de junho de 2010
  • 8. DoctrineCommon git@github.com:doctrine/common.git  Cache Drivers sábado, 26 de junho de 2010
  • 9. DoctrineCommonCache  Drivers Suportados:  APCCache $cacheDriver = new DoctrineCommonCacheApcCache();  MemcacheCache $memcache = new Memcache(); $memcache->addServer('memcache_host', 11211); $cacheDriver = new DoctrineCommonCacheMemcacheCache(); $cacheDriver->setMemcache($memcache);  XcacheCache $cacheDriver = new DoctrineCommonCacheXcacheCache(); sábado, 26 de junho de 2010
  • 10. DoctrineCommonCache  Cache Drivers Interface: interface DoctrineCommonCacheCache { 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
  • 11. DoctrineCommon git@github.com:doctrine/common.git  Cache Drivers  Class Loader sábado, 26 de junho de 2010
  • 12. DoctrineCommonClassLoader  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
  • 13. DoctrineCommonClassLoader  Como usar: require_once '/path/to/lib/Doctrine/Common/ClassLoader.php'; $doctrineClassLoader = new DoctrineCommonClassLoader( 'Doctrine', '/path/to/lib/Doctrine' ); $doctrineClassLoader->register(); sábado, 26 de junho de 2010
  • 14. DoctrineCommon git@github.com:doctrine/common.git  Cache Drivers  Class Loader  Collections sábado, 26 de junho de 2010
  • 15. DoctrineCommonCollections  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
  • 16. DoctrineCommon git@github.com:doctrine/common.git  Cache Drivers  Class Loader  Collections  Lexer sábado, 26 de junho de 2010
  • 17. DoctrineCommon git@github.com:doctrine/common.git  Cache Drivers  Class Loader  Collections  Lexer  Annotations Parser sábado, 26 de junho de 2010
  • 18. DoctrineCommonAnnotations  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
  • 19. DoctrineCommonAnnotations Annotations ::= Annotation {[ "*" ]* [Annotation]}* Annotation ::= "@" AnnotationName ["(" [Values] ")"] AnnotationName ::= QualifiedName | SimpleName | AliasedName QualifiedName ::= NameSpacePart "" {NameSpacePart ""}* SimpleName AliasedName ::= Alias ":" SimpleName NameSpacePart ::= identifier SimpleName ::= identifier Alias ::= identifier Values ::= Array | Value {"," Value}* Value ::= PlainValue | FieldAssignment PlainValue ::= integer | string | float | boolean | Array | Annotation FieldAssignment ::= FieldName "=" PlainValue FieldName ::= identifier Array ::= "{" ArrayEntry {"," ArrayEntry}* "}" ArrayEntry ::= Value | KeyValuePair KeyValuePair ::= Key "=" PlainValue Key ::= string | integer sábado, 26 de junho de 2010
  • 20. DoctrineCommonAnnotations  Criando classes de Annotations: final class DoctrineORMMappingEntity extends DoctrineCommonAnnotationsAnnotation { public $repositoryClass; }  Usando as Annotations: namespace MyProjectEntity; /** * @Entity(repositoryClass="RepositoryUserRepository") */ class User { // ... } sábado, 26 de junho de 2010
  • 21. DoctrineCommonAnnotations  Lendo Annotations: $reader = new DoctrineCommonAnnotationsAnnotationReader( new DoctrineCommonCacheArrayCache() ); $reader->setDefaultAnnotationNamespace( 'DoctrineORMMapping' ); $class = new ReflectionClass('MyProjectEntityUser'); $classAnnotations = $reader->getClassAnnotations($class); echo $classAnnotations['DoctrineORMMappingEntity'] ->repositoryClass; sábado, 26 de junho de 2010
  • 22. DoctrineCommonAnnotations interface DoctrineCommonAnnotationsAnnotationReader { 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
  • 23. DoctrineDBAL git@github.com: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
  • 24. DoctrineDBAL  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
  • 25. DoctrineDBAL interface DoctrineDBALConnection { // 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 DBALStatement */ function prepare($statement); /* Aplica um SQL statement e retorna # linhas afetadas. */ function exec($statement); // ... sábado, 26 de junho de 2010
  • 26. DoctrineDBAL // 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
  • 27. DoctrineDBAL // 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
  • 28. DoctrineDBALTypes  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
  • 29. DoctrineDBALTypes  Novo tipo é só implementar uma classe abstrata: interface DoctrineDBALTypesType { 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
  • 30. DoctrineDBAL class MyProjectDataTypesMyObjectType extends DoctrineDBALTypesType { 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
  • 31. DoctrineDBALTypes  Finalmente, faça o Doctrine saber sobre seu tipo: DoctrineDBALTypesType::addType( "my-object", "MyProjectDataTypesMyObjectType" );  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
  • 32. DoctrineDBAL  Criando um schema: $platform = $em->getConnection()->getDatabasePlatform(); $schema = new DoctrineDBALSchemaSchema(); $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
  • 33. DoctrineDBAL  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
  • 34. DoctrineDBAL  Comparando schemas: $platform = $em->getConnection()->getDatabasePlatform(); $fromSchema = new DoctrineDBALSchemaSchema(); $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
  • 35. DoctrineDBAL  Comparando schemas: $platform = $em->getConnection()->getDatabasePlatform(); $toSchema = new DoctrineDBALSchemaSchema(); $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
  • 36. DoctrineDBAL  Comparando schemas: $platform = $em->getConnection()->getDatabasePlatform(); $comparator = new DoctrineDBALSchemaComparator(); $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
  • 37. 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
  • 38. 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
  • 39. Performance em Inserções  Sem palhaçada aqui! =P Qual 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
  • 40. 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
  • 41. 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
  • 42. 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
  • 43. DoctrineORM  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
  • 44. DoctrineORM  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
  • 45. DoctrineORM  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
  • 46. DoctrineORM  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
  • 47. DoctrineORM  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
  • 48. DoctrineORM  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
  • 49. DoctrineORM  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
  • 50. DoctrineORM namespace 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
  • 51. DoctrineORM EntityUser: type: entity table: users id: id: type: integer generator: strategy: AUTO fields: name: type: string length: 32 sábado, 26 de junho de 2010
  • 52. DoctrineORM <?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-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="EntityUser" 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
  • 53. DoctrineORM  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
  • 54. DoctrineORM  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
  • 55. DoctrineORM  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
  • 56. DoctrineORM  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
  • 57. DoctrineORM /** @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
  • 58. DoctrineORM CREATE 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
  • 59. DoctrineORM  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
  • 60. DoctrineORM namespace MyProjectEntity; /** * @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
  • 61. DoctrineORM  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
  • 62. DoctrineORM namespace MyProjectEntity; /** * @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
  • 63. DoctrineORM  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
  • 64. DoctrineORM  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
  • 65. DoctrineORM interface DoctrineORMEntityManager { // 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
  • 66. DoctrineORM // Query API /* Creates a new Query object. */ function createQuery($dql); /* Creates a native SQL query. */ function createNativeQuery( $sql, DoctrineORMQueryResultSetMapping $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
  • 67. DoctrineORM // 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
  • 68. DoctrineORM // 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
  • 69. DoctrineORM  Trabalhando com Entidades no EntityManager  Criando o EntityManager $config = new DoctrineORMConfiguration(); $config->setMetadataCacheImpl($cacheDriver); $config->setQueryCacheImpl($cacheDriver); $config->setProxyDir("/path/to/MyProject/Proxies"); $config->setProxyNamespace("MyProjectProxies"); $connectionOptions = array( "driver" => "pdo_sqlite", "path" => "database.sqlite" ); // Creating the EntityManager $em = DoctrineORMEntityManager::create( $connectionOptions, $config ); sábado, 26 de junho de 2010
  • 70. DoctrineORM  Trabalhando com Entidades no EntityManager  Persistindo Entidades try { $em->transactional(function ($em) { $user = new MyProjectEntityUser(); $user->name = "Guilherme Blanco"; $em->persist($user); }); } catch (Exception $e) { // ... } sábado, 26 de junho de 2010
  • 71. DoctrineORM  Trabalhando com Entidades no EntityManager  Atualizando Entidades try { $em->transactional(function ($em) { $user = $em->find("MyProjectEntityUser", 1); $user->name = "Benjamin Eberlei"; $em->persist($user); }); } catch (Exception $e) { // ... } sábado, 26 de junho de 2010
  • 72. DoctrineORM  Trabalhando com Entidades no EntityManager  Removendo Entidades try { $em->transactional(function ($em) { $user = $em->getReference("MyProjectEntityUser", 1); $em->remove($user); }); } catch (Exception $e) { // ... } sábado, 26 de junho de 2010
  • 73. DoctrineORM  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 MyProjectEntityUser u" ); $users = $query->execute(); sábado, 26 de junho de 2010
  • 74. DoctrineORM  Native Query  Possibilitavoltar ao poder da SQL sem perder a habilidade de hidratar seus dados na sua Entidade $rsm = new DoctrineORMQueryResultSetMapping(); $rsm->addEntityResult("MyProjectEntityUser", "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
  • 75. DoctrineORM  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("MyProjectEntityUser", "u"); $users = $qb->getQuery()->execute(); sábado, 26 de junho de 2010
  • 76. DoctrineORM  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 MyProjectEntityUser u" ); $query->useResultCache(true, 3600, "my_custom_name"); sábado, 26 de junho de 2010
  • 77. DoctrineORM  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 DoctrineDBALToolsConsoleHelperConnectionHelper( $em->getConnection() ), 'db' ); $helperSet->set( new DoctrineORMToolsConsoleHelperEntityManagerHelper( $em ), 'em' ); $cli->addCommands(array(...)); sábado, 26 de junho de 2010
  • 78. DoctrineORM  Comandos disponíveis:  DoctrineDBALToolsConsoleCommandRunSqlCommand  DoctrineDBALToolsConsoleCommandImportCommand  DoctrineORMToolsConsoleCommandClearCacheMetadataCommand  DoctrineORMToolsConsoleCommandClearCacheResultCommand  DoctrineORMToolsConsoleCommandClearCacheQueryCommand  DoctrineORMToolsConsoleCommandSchemaToolCreateCommand  DoctrineORMToolsConsoleCommandSchemaToolUpdateCommand  DoctrineORMToolsConsoleCommandSchemaToolDropCommand  DoctrineORMToolsConsoleCommandConvertDoctrine1SchemaCommand  DoctrineORMToolsConsoleCommandConvertMappingCommand  DoctrineORMToolsConsoleCommandGenerateRepositoriesCommand  DoctrineORMToolsConsoleCommandGenerateEntitiesCommand  DoctrineORMToolsConsoleCommandGenerateProxiesCommand  DoctrineORMToolsConsoleCommandEnsureProductionSettingsCommand  DoctrineORMToolsConsoleCommandValidateSchemaCommand  DoctrineORMToolsConsoleCommandRunDqlCommand sábado, 26 de junho de 2010
  • 79. 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
  • 80. Questions?  Guilherme Blanco  Informações de contato:  @guilhermeblanco  guilhermeblanco@php.net  http://www.facebook.com/guilhermeblanco  +55 16 9215.8480  OBRIGADO PELA PACIÊNCIA!!! =) sábado, 26 de junho de 2010