Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Guilherme Blanco, Yahoo!


          Doctrine 2
           Camada de Persistência para PHP 5.3+




sábado, 26 de junho de...
Quem sou eu?
        Web developer a mais de 10 anos

        Evangelista Open Source

        Trabalha para Yahoo!

  ...
Quem sou eu?
        http://www.twitter.com/guilhermeblanco

        http://www.facebook.com/guilhermeblanco




sábado,...
Doctrine 2



sábado, 26 de junho de 2010
Doctrine 2
        PHP 5.3+

        100% do código reescrito

        Código totalmente em namespaces




sábado, 26 d...
Doctrine 2
        Ferramentas usadas:
            phpUnit  Unit test
            Phing Pacotes e distribuição
        ...
Doctrine 2
        Três principais pacotes:
            Common


            DBAL


            ORM




sábado, 26 de ...
DoctrineCommon
     git@github.com:doctrine/common.git

        Cache Drivers




sábado, 26 de junho de 2010
DoctrineCommonCache
        Drivers Suportados:
            APCCache
     $cacheDriver = new DoctrineCommonCacheApcCache...
DoctrineCommonCache
        Cache Drivers Interface:
     interface DoctrineCommonCacheCache {
       function setNamespa...
DoctrineCommon
     git@github.com:doctrine/common.git

        Cache Drivers

        Class Loader




sábado, 26 de ju...
DoctrineCommonClassLoader
        Implements PSR #0
            PSR       = PHP Standards Recommendation

            I...
DoctrineCommonClassLoader
        Como usar:

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

     $do...
DoctrineCommon
     git@github.com:doctrine/common.git

        Cache Drivers

        Class Loader

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

        Array simples em PHP são ...
DoctrineCommon
     git@github.com:doctrine/common.git

        Cache Drivers

        Class Loader

        Collection...
DoctrineCommon
     git@github.com:doctrine/common.git

        Cache Drivers

        Class Loader

        Collection...
DoctrineCommonAnnotations
        Suporte à Annotations similar ao Java

        Define informações de metadados em clas...
DoctrineCommonAnnotations
     Annotations              ::=   Annotation {[ "*" ]* [Annotation]}*
     Annotation         ...
DoctrineCommonAnnotations
        Criando classes de Annotations:
     final class DoctrineORMMappingEntity
         exte...
DoctrineCommonAnnotations
        Lendo Annotations:
     $reader = new DoctrineCommonAnnotationsAnnotationReader(
      ...
DoctrineCommonAnnotations
     interface DoctrineCommonAnnotationsAnnotationReader {
       function setDefaultAnnotationN...
DoctrineDBAL
     git@github.com:doctrine/dbal.git

        DataBase Abstraction Layer construído sobre a PDO e
         ...
DoctrineDBAL
        API para introspecção e gerenciamento de
         schemas de Bancos de Dados melhorado

        Pod...
DoctrineDBAL
     interface DoctrineDBALConnection {
       // API para manipulação de dados

        /* Executa um SQL DE...
DoctrineDBAL
        // API para Transação

        /* Retorna o nível de profundidade da transação corrente. */
        f...
DoctrineDBAL
         // API para obtenção de dados

         /* Executa consulta SQL e retorna a 1a. linha num array asso...
DoctrineDBALTypes
        Ponto centralizado para conversão de tipos
            Do Banco de Dados para PHP
           ...
DoctrineDBALTypes
        Novo tipo é só implementar uma classe abstrata:
    interface DoctrineDBALTypesType {
        f...
DoctrineDBAL
     class MyProjectDataTypesMyObjectType extends DoctrineDBALTypesType
     {
       public function getSqlD...
DoctrineDBALTypes
        Finalmente, faça o Doctrine saber sobre seu tipo:
    DoctrineDBALTypesType::addType(
        "...
DoctrineDBAL
        Criando um schema:
    $platform = $em->getConnection()->getDatabasePlatform();

    $schema = new D...
DoctrineDBAL
        Removendo um schema:
    // obtém as queries para remover o schema em segurança.
    $queries = $sch...
DoctrineDBAL
        Comparando schemas:
    $platform = $em->getConnection()->getDatabasePlatform();

    $fromSchema = ...
DoctrineDBAL
        Comparando schemas:
     $platform = $em->getConnection()->getDatabasePlatform();

     $toSchema = ...
DoctrineDBAL
        Comparando schemas:
    $platform = $em->getConnection()->getDatabasePlatform();

    $comparator = ...
Performance em Inserções
        Inserindo 20 entradas com Doctrine 2:
    for ($i = 0; $i < 20; $i++) {
        $user = ...
Performance em Inserções
        Inserindo 20 entradas com código PHP “crú”:
    $start = microtime(0);

    for ($i = 0;...
Performance em Inserções
        Sem palhaçada aqui! =P
         Qual deles vocês acham que é mais rápido?
            D...
Performance em Inserções
        Doctrine 2 *NÃO É* mais rápido que código PHP
         puro

        Desenvolvedores pa...
Performance em Inserções
        Inserindo 20 entradas com código PHP “crú”:
    $start = microtime(0);

    mysql_query(...
Performance em Inserções
        Informações finais de performance...
            Doctrine          2
                 ...
DoctrineORM
        O que aprendemos com Doctrine 1?
            Camada   de Persistência != Modelo de Domínio
         ...
DoctrineORM
        Comparação de performance
            Hidratar         5000 registros
                  Doctrine 1....
DoctrineORM
        Por que é mais rápido?
            Otimizações      do PHP 5.3!
                  30% menos recurso...
DoctrineORM
        Por que extingüir a mágica?
            Eliminar         o fator PQP/minuto

            Difícil
  ...
DoctrineORM
        Como extingüir a mágica?
            Nós      chamamos de POO!

            Composição
           ...
DoctrineORM
        DataMapper ao invés de ActiveRecord

        Densamente inspirado em JSR-317/JPA v2.0

        Java...
DoctrineORM
        Entidades
            Classe PHP regular
            Objeto persistente de domínio enxuto
         ...
DoctrineORM
     namespace Entity;

     /**
      * @Entity
      * @Table(name="users")
      */
     class User {
     ...
DoctrineORM
    EntityUser:
      type: entity
      table: users
      id:
        id:
          type: integer
          ...
DoctrineORM
    <?xml version="1.0" encoding="UTF-8"?>
    <doctrine-mapping
       xmlns="http://doctrine-project.org/sch...
DoctrineORM
        Mapeamento de Colunas
            type
            length
            scale, precision
           ...
DoctrineORM
        Campos identificadores
            Suporta          diferentes estratégias:
                  AUTO
...
DoctrineORM
        Campos de associação
              OneToOne
    /** @OneToOne(targetEntity="Shipping") */
    privat...
DoctrineORM
        Herança
            Concrete         Table Inheritance
                  Sem colunas irrelevantes
 ...
DoctrineORM
     /** @MappedSuperclass */
     class MappedSuperclassBase {
         /** @Column(type="string") */
       ...
DoctrineORM
     CREATE TABLE users (
         mapped TEXT NOT NULL,
         id INTEGER NOT NULL,
         name TEXT NOT ...
DoctrineORM
        Herança
            Single       Table Inheritance
                  Somente uma tabela na base de ...
DoctrineORM
     namespace MyProjectEntity;

     /**
       * @Entity
       * @InheritanceType("SINGLE_TABLE")
       * ...
DoctrineORM
        Herança
            Class       Table Inheritance
                  Fácil de entender
             ...
DoctrineORM
     namespace MyProjectEntity;

     /**
       * @Entity
       * @InheritanceType("JOINED")
       * @Discr...
DoctrineORM
        Proxies
            Carga-tardia dos dados da Entidade
            Provê a possibilidade de obter u...
DoctrineORM
        EntityManager
            Ponto   central da funcionalidade ORM
            Aplica a estratégia de ...
DoctrineORM
     interface DoctrineORMEntityManager {
         // Transaction API

           /* Starts a transaction on t...
DoctrineORM
           // Query API

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

...
DoctrineORM
           // Object Manipulation API

           /* Tells EntityManager to make instance managed and persiste...
DoctrineORM
           // Repository, Configuration, EventManager, etc

           /* Gets the EventManager used by the En...
DoctrineORM
        Trabalhando com Entidades no EntityManager
              Criando o EntityManager
    $config = new D...
DoctrineORM
        Trabalhando com Entidades no EntityManager
              Persistindo Entidades
    try {
        $em...
DoctrineORM
        Trabalhando com Entidades no EntityManager
              Atualizando Entidades
    try {
        $em...
DoctrineORM
        Trabalhando com Entidades no EntityManager
              Removendo Entidades
    try {
        $em->...
DoctrineORM
        Doctrine Query Language (DQL)
            Implementação   de uma OQL
            Fortemente influen...
DoctrineORM
        Native Query
            Possibilitavoltar ao poder da SQL sem perder a
              habilidade de ...
DoctrineORM
        QueryBuilder
            Implementação  de um Builder
            Construção e execução são separad...
DoctrineORM
        Doctrine suporta diferentes níveis de cache
            Metadata           cache
    $config->setMet...
DoctrineORM
        Console
            Usa o componente Symfony 2 Console
            Auxilia a desenvolver com Doctri...
DoctrineORM
        Comandos disponíveis:
              DoctrineDBALToolsConsoleCommandRunSqlCommand
              Doct...
Future
        DBAL
            QueryBuilder
            Concluir o driver MSSQL Server



        DQL
            Su...
Questions?
        Guilherme Blanco
            Informações       de contato:

                    @guilhermeblanco

  ...
Upcoming SlideShare
Loading in …5
×

Doctrine2 Seminário PHP

8,154 views

Published on

Published in: Technology

Doctrine2 Seminário PHP

  1. 1. Guilherme Blanco, Yahoo! Doctrine 2 Camada de Persistência para PHP 5.3+ sábado, 26 de junho de 2010
  2. 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. 3. Quem sou eu?  http://www.twitter.com/guilhermeblanco  http://www.facebook.com/guilhermeblanco sábado, 26 de junho de 2010
  4. 4. Doctrine 2 sábado, 26 de junho de 2010
  5. 5. Doctrine 2  PHP 5.3+  100% do código reescrito  Código totalmente em namespaces sábado, 26 de junho de 2010
  6. 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. 7. Doctrine 2  Três principais pacotes:  Common  DBAL  ORM sábado, 26 de junho de 2010
  8. 8. DoctrineCommon git@github.com:doctrine/common.git  Cache Drivers sábado, 26 de junho de 2010
  9. 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. 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. 11. DoctrineCommon git@github.com:doctrine/common.git  Cache Drivers  Class Loader sábado, 26 de junho de 2010
  12. 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. 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. 14. DoctrineCommon git@github.com:doctrine/common.git  Cache Drivers  Class Loader  Collections sábado, 26 de junho de 2010
  15. 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. 16. DoctrineCommon git@github.com:doctrine/common.git  Cache Drivers  Class Loader  Collections  Lexer sábado, 26 de junho de 2010
  17. 17. DoctrineCommon git@github.com:doctrine/common.git  Cache Drivers  Class Loader  Collections  Lexer  Annotations Parser sábado, 26 de junho de 2010
  18. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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

×