doctrine 2 orm

239
Doctrine 2 ORM Documentation Release 2.1 Doctrine Project Team :: Traducido por Nacho Pacheco November 03, 2011

Upload: kiesito

Post on 10-Oct-2015

193 views

Category:

Documents


0 download

DESCRIPTION

Doctrine 2 ORM Documentation

TRANSCRIPT

  • 5/20/2018 Doctrine 2 Orm

    1/239

    Doctrine 2 ORM DocumentationRelease 2.1

    Doctrine Project Team :: Traducido por Nacho Pacheco

    November 03, 2011

  • 5/20/2018 Doctrine 2 Orm

    2/239

  • 5/20/2018 Doctrine 2 Orm

    3/239

    ndice general

    1. Gua de referencia 1

    1.1. Introduccin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

    1.2. Arquitectura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

    1.3. Configurando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

    1.4. Preguntas ms frecuentes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

    1.5. Asignacin bsica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

    1.6. Asignando asociaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

    1.7. Asignando herencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

    1.8. Trabajando con objetos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

    1.9. Trabajando con asociaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

    1.10. Transacciones y concurrencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

    1.11. Eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 751.12. Procesamiento masivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

    1.13. Lenguaje de consultaDoctrine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

    1.14. El generador de consultas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

    1.15. SQLnativo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

    1.16. Change Tracking Policies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

    1.17. Partial Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

    1.18. Asignacin XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

    1.19. Asignacin YAML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

    1.20. Referencia de anotaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136

    1.21. PHP Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

    1.22. Memoria cach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

    1.23. Mejorando el rendimiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

    1.24. Herramientas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1591.25. Metadata Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

    1.26. Buenas prcticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

    1.27. Limitations and Known Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169

    2. Guas iniciales 173

    2.1. Primeros pasos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173

    2.2. Trabajando con asociaciones indexadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

    2.3. Extra Lazy Associations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197

    I

  • 5/20/2018 Doctrine 2 Orm

    4/239

    2.4. Composite and Foreign Keys as Primary Key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198

    3. Recetario 205

    3.1. Campos agregados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205

    3.2. ExtendiendoDQLen Doctrine 2: PaseantesASTpersonalizados . . . . . . . . . . . . . . . . . . . . 210

    3.3. FuncionesDQLdefinidas por el usuario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213

    3.4. Implementing ArrayAccess for Domain Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2173.5. Implementing the Notify ChangeTracking Policy . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218

    3.6. Implementing Wakeup or Clone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219

    3.7. Integrating with CodeIgniter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220

    3.8. SQL-Table Prefixes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223

    3.9. Strategy-Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224

    3.10. Validation of Entities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228

    3.11. Working with DateTime Instances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230

    3.12. Mysql Enums. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232

    II

  • 5/20/2018 Doctrine 2 Orm

    5/239

    CAPTULO 1

    Gua de referencia

    1.1 Introduccin

    1.1.1 Bienvenido

    Doctrine 2 es un asignador objetorelacional (ORM) para PHP 5.3.0+ que proporciona persistencia transparente de

    objetos PHP. Se sita en la parte superior de una poderosa capa de abstraccin de base de datos (DBAL por DataBase

    Abstraction Layer). La principal tarea de los asignadores objetorelacionales es la traduccin transparente entre objetos

    (PHP) y las filas relacionales de la base de datos.

    Una de las caractersticas clave de Doctrinees la opcin de escribir las consultas de base de datos en un dialecto SQL

    propio orientado a objetos llamado Lenguaje de Consulta Doctrine(DQLpor Doctrine Query Language), inspirado

    en Hibernates HQL. Adems DQL difiere ligeramente de SQL en que abstrae considerablemente la asignacin entre

    las filas de la base de datos y objetos, permitiendo a los desarrolladores escribir poderosas consultas de una manera

    sencilla y flexible.

    1.1.2 Descargo de responsabilidad

    Esta es la documentacin de referencia de Doctrine 2. Las guas introductorias y tutoriales que puedes seguir de

    principio a fin, como el libro Gua para Doctrine ms conocido de la serie Doctrine1.x, estar disponible en una

    fecha posterior.

    1.1.3 Usando un asignador objetorelacional

    Cmo insina el trmino ORM, Doctrine2 tiene como objetivo simplificar la traduccin entre las filas de la base de

    datos y el modelo de objetos PHP. El caso de uso principal para Doctrine, por lo tanto son las aplicaciones que utilizanel paradigma de programacin orientado a objetos. Para aplicaciones que no trabajan principalmente con objetos,

    Doctrine2 no se adapta muy bien.

    1.1.4 Requisitos

    Doctrine2 requiere un mnimo de PHP 5.3.0. Para obtener un rendimiento mejorado en gran medida, tambin se

    recomienda que utilices APC con PHP.

    1

  • 5/20/2018 Doctrine 2 Orm

    6/239

    Doctrine 2 ORM Documentation, Release 2.1

    1.1.5 PaquetesDoctrine2

    Doctrine2 se divide en tres paquetes principales.

    Comn

    DBAL (incluye Comn)

    ORM (incluye DBAL+Comn)

    Este manual cubre principalmente el paquete ORM, a veces toca partes de los paquetes subyacentes DBAL y Comn.

    El cdigo base de Doctrineest dividido en estos paquetes por varias razones y se van a ...

    ... Hace las cosas ms fciles de mantener y desacopladas

    ... te permite usar cdigo de Doctrinecomn sin el ORM o DBAL

    ... te permite usar DBAL sin el ORM

    El paquete Comn

    El paquete Comn contiene componentes altamente reutilizables que no tienen dependencias ms all del propio

    paquete (y PHP, por supuesto). El espacio de nombres raz del paquete Comn es Doctrine\Common.

    El paquete DBAL

    El paquete DBAL contiene una capa de abstraccin de base de datos mejorada en lo alto de PDO, pero no est vinculada

    fuertemente a PDO. El propsito de esta capa es proporcionar una sola APIque fusione la mayor parte de las diferen-

    cias entre los diferentes proveedores RDBMS. El espacio de nombres raz del paquete DBAL esDoctrine\DBAL.

    El paquete ORM

    El paquete ORM contiene las herramientas de asignacin objetorelacional que proporcionan persistencia relacional

    transparente de objetos PHP sencillos. El espacio de nombres raz del paquete ORM es Doctrine\ORM.

    1.1.6 Instalando

    Puedes instalar Doctrinede diferentes maneras. Vamos a describir todas las diferentes maneras y t puedes elegir la

    que mejor se adapte a tus necesidades.

    PEAR

    Puedes instalar cualquiera de los tres paquetes de Doctrine desde la utilidad de instalacin de la lnea de ordenes

    PEAR.

    Para instalar slo el paquete Comnpuedes ejecutar la siguiente orden:

    $ sudo pear install pear.doctrine-project.org/DoctrineCommon-

    Si deseas utilizar la capa de abstraccin de base de datos de Doctrinela puedes instalar con la siguiente orden.

    $ sudo pear install pear.doctrine-project.org/DoctrineDBAL-

    O, si quieres conseguir las tareas e ir por el ORM lo puedes instalar con la siguiente orden.

    2 Captulo 1. Gua de referencia

  • 5/20/2018 Doctrine 2 Orm

    7/239

    Doctrine 2 ORM Documentation, Release 2.1

    $ sudo pear install pear.doctrine-project.org/DoctrineORM-

    Nota: La etiqueta anterior representa la versin que deseas instalar. Por ejemplo, si la versin actual al

    momento de escribir esto es 2.0.7para el ORM, por lo tanto la podras instalar con lo siguiente:

    $ sudo pear install pear.doctrine-project.org/DoctrineORM-2.0.7

    Cuando instalas un paquete mediante PEAR puedes requerir y cargar el cargador de clases ClassLoader con el

    siguiente cdigo.

  • 5/20/2018 Doctrine 2 Orm

    8/239

    Doctrine 2 ORM Documentation, Release 2.1

    Descargando el paquete

    Tambin puedes utilizarDoctrine2 descargando la ltima versin del paquete de la pgina de descarga.

    Ve la seccin de configuracin sobre cmo configurar y arrancar una versin de Doctrinedescargada.

    GitHub

    Alternativamente, puedes clonar la ltima versin de Doctrine2 a travs de GitHub.com:

    $ git clone git://github.com/doctrine/doctrine2.git doctrine

    Esto descarga todas las fuentes del paquete ORM. Necesitas iniciar los submdulos Github para las dependencias del

    paqueteCommony DBAL:

    $ git submodule init

    $ git submodule update

    Esto actualiza a Git para utilizar Doctriney las versiones de los paquetes recomendados de Doctrinepara la versin

    Maestra clonada deDoctrine2.

    Consulta el captulo de configuracin sobre cmo configurar una instalacin Github de Doctrine con respecto a la

    carga automtica.

    NOTA

    No debes combinar consignaciones Doctrine-Common, Doctrine-DBALy Doctrine-ORMmaestras con

    las dems en combinacin. El ORM posiblemente no funcione con las versiones maestras de Commono

    DBALactuales. En su lugar el ORM viene con los submdulos Git que se requieren.

    Subversion

    NOTA

    Usar el espejo SVN no es recomendable. Este slo te permite acceso a la ltima confirmacin maestra yno busca los submdulos automticamente.

    Si prefieres subversin tambin puedes descargar el cdigo desde GitHub.com a travs del protocolo de subversin:

    $ svn co http://svn.github.com/doctrine/doctrine2.git doctrine2

    Sin embargo, esto slo te permite ver el maestro de Doctrine 2 actual, sin las dependencias Common y DBAL. Las

    tienes que tomar t mismo, pero te podras encontrar con incompatibilidad entre las versiones de las diferentes ramas

    maestras Common,DBALy ORM.

    Inicio rpido con el recinto de seguridad

    NOTA El recinto de seguridad slo est disponible a travs del repositorio Github de Doctrine2 o tanpronto como lo descargues por separado en la pgina de descargas. Lo encontrars en el directorio

    $root/tools/sandbox.

    El recinto de seguridad es un entorno preconfigurado para evaluar y jugar con Doctrine2.

    4 Captulo 1. Gua de referencia

    http://www.doctrine-project.org/downloadhttp://www.doctrine-project.org/downloadhttp://www.doctrine-project.org/download
  • 5/20/2018 Doctrine 2 Orm

    9/239

    Doctrine 2 ORM Documentation, Release 2.1

    1.1.7 Descripcin

    Despus de navegar por el directoriosandbox, deberas ver la siguiente estructura:

    sandbox/

    Entities/

    Address.php

    User.phpxml/

    Entities.Address.dcm.xml

    Entities.User.dcm.xml

    yaml/

    Entities.Address.dcm.yml

    Entities.User.dcm.yml

    cli-config.php

    doctrine

    doctrine.php

    index.php

    Aqu est un breve resumen del propsito de estos directorios y archivos:

    El directorioEntitieses donde se han creado las clases del modelo. All estn dos entidades de ejemplo.

    El directorio xmles donde se crean todos los archivos de asignacin XML (si deseas utilizar la asignacin

    XML). Ya estn all dos ejemplos de asignacin de documentos para 2 entidades de ejemplo.

    El directorio yaml es donde se crean los archivos de asignacin YAML (si deseas utilizar la asignacin YAML).

    Ya estn all dos ejemplos de asignacin de documentos para 2 entidades de ejemplo.

    cli-config.phpcontiene cdigo de arranque para una configuracin que utiliza la herramienta de consola

    doctrinecada vez que se ejecuta una tarea.

    doctrine/doctrine.phpes una herramienta de lnea de ordenes.

    index.phpes un archivo de arranque clsico de una aplicacin php que utilizaDoctrine2.

    Minitutorial

    1. Desde el directoriotools/sandbox, ejecuta la siguiente orden y deberas ver el mismo resultado.

    $ php doctrine orm:schema-tool:create

    Creando el esquema de base de datos...

    Esquema de base de datos creado satisfactoriamente!

    2. Dale otro vistazo al directoriotools/sandbox. Se ha creado un esquema de base de datos SQLite con el

    nombre database.sqlite.

    3. Abreindex.phpy en la parte inferior haz las correcciones necesarias para que sea de la siguiente manera:

  • 5/20/2018 Doctrine 2 Orm

    10/239

    Doctrine 2 ORM Documentation, Release 2.1

    Abre index.php en el navegador o ejectalo en la lnea de ordenes. Deberas ver guardado por el usuario!.

    4. Inspecciona la base de datos SQLite. Una vez ms dentro del directorio/sandbox, ejecuta la siguiente

    orden:

    $ php doctrine dbal:run-sql select * from usersDebes obtener la siguiente salida:

    array(1) {

    [0]=>

    array(2) {

    ["id"]=>

    string(1) "1"

    ["name"]=>

    string(8) "Garfield"

    }

    }

    Acabas de guardar tu primera entidad con un identificador generado en una base de datos SQLite.

    5. Reemplaza el contenido deindex.phpcon lo siguiente:

  • 5/20/2018 Doctrine 2 Orm

    11/239

    Doctrine 2 ORM Documentation, Release 2.1

    1.2.1 Entidades

    Una entidad es un ligero, objeto persistente del dominio. Una entidad puede ser cualquier clase PHP regular que

    observa las siguientes restricciones:

    Una clase entidad no debe ser final o contener mtodos final.

    Todas las propiedades persistentes/campo de cualquier clase de entidad siempre deben ser privadas o protegidas,de lo contrario la carga diferida podra no funcionar como se espera.

    Una clase entidad no debe implementar __cloneo debehacerlo de manera segura.

    Una clase entidad no debe implementar __wakeup o debe hacerlo de manera segura. Tambin considera

    implementar serializableen su lugar.

    Cualquiera de las dos clases entidad en una jerarqua de clases que heredan directa o indirectamente la una de

    la otra, no deben tener asignada una propiedad con el mismo nombre. Es decir, si B hereda de A entonce B no

    debe tener un campo asignado con el mismo nombre que un campo ya asignado heredado de A.

    Una entidad no puede usar func_get_args()para implementar parmetros variables. Los delegados

    generados no son compatibles con este por razones de rendimiento y tu cdigo en realidad podra dejar de

    funcionar cuando viola esta restriccin.

    Las entidades admiten la herencia, asociaciones polimrficas, y consultas polimrficas. Ambas clases abstractas y

    especficas pueden ser entidades. Las entidades pueden extender clases que no son entidad, as como clases entidad, y

    las clases que no son entidad pueden extender a las clases entidad.

    Truco El constructor de una entidad slo se invoca cuando t construyes una nueva instancia con la

    palabra clave new. Doctrine nunca llama a los constructores de la entidad, por lo tanto eres libre de

    utilizarlos como desee e incluso tienes que requerir argumentos de algn tipo.

    Estados de la entidad

    Una instancia de entidad se puede caracterizar como NEW,MANAGED,DETACHEDo REMOVED.

    Una NEW instancia de la entidad no tiene identidad persistente, y todava no est asociada con unEntityManagery UnitOfWork(es decir, se acaba de crear con el operador new).

    Una instancia de la entidad MANAGED es una instancia con una identidad persistente que se asocia con un

    EntityManagery cuya persistencia se maneja as.

    A instancia de entidad DETACHEDes una instancia con una identidad persistente que no es (o no) asociada a

    unEntityManagery unaUnitOfWork.

    A instancia de entidadREMOVEDes una instancia con una identidad persistente, asociada a unEntityManager,

    que se eliminar de la base de datos al confirmar la transaccin.

    Campos persistentes

    El estado persistente de una entidad lo representan las variables de la instancia. Una variable de instancia se debeacceder directamente slo desde dentro de los mtodos de la entidad por la instancia de la entidad en s. Las variables

    de instancia no se deben acceder por los clientes de la entidad. El estado de la entidad est a disposicin de los clientes

    solamente a travs de los mtodos de la entidad, es decir, mtodos de acceso (mtodos captador/definidor) u otros

    mtodos del negocio.

    Una coleccin valorada de campos persistentes y las propiedades se debe definir en trminos de la interfaz

    Doctrine\Common\Collections\Collection. El tipo de implementacin de la coleccin se puede utili-

    zar por la aplicacin para iniciar los campos o propiedades antes de persistir la entidad. Una vez que la entidad se

    manej (o separ), el posterior acceso debe ser a travs del tipo de la interfaz.

    1.2. Arquitectura 7

    http://de3.php.net/manual/es/class.serializable.phphttp://de3.php.net/manual/es/class.serializable.php
  • 5/20/2018 Doctrine 2 Orm

    12/239

    Doctrine 2 ORM Documentation, Release 2.1

    Serializando entidades

    La serializacin de entidades puede ser problemtica y no se recomienda en realidad, al menos no mientras una instan-

    cia de la entidad an mantenga referencias a objetos delegados o si todava est gestionada por un EntityManager.

    Si vas a serializar (y deserializar) instancias de la entidad que todava mantienen referencias a objetos delegados

    puedes tener problemas con la propiedad privada debido a limitaciones tcnicas. Los objetos delegados implementan

    __sleepy __sleepno tiene la posibilidad para devolver nombres de las propiedades privadas de las clases padre.Por otro lado, no es una solucin para los objetos delegados implementar serializable porque serializable

    no funciona bien con todas las referencias a objetos potencialmente cclicas (por lo menos no hemos encontrado una

    manera, sin embargo, si lo consigues, por favor ponte en contacto con nosotros).

    1.2.2 ElEntityManager

    La claseEntityManageres un punto de acceso central a la funcionalidad ORM proporcionada por Doctrine2. La

    APIde EntityManager se utiliza para gestionar la persistencia de los objetos y para consultar objetos persistentes.

    Escritura transaccionales en segundo plano

    Un EntityManager y la UnitOfWork subyacente emplean una estrategia denominada escritura transaccional

    en segundo plano, que retrasa la ejecucin de las declaraciones SQL con el fin de ejecutarlas de la manera ms

    eficiente y para ejecutarlas al final de una transaccin, de forma que todos los bloqueos de escritura sean liberados

    rpidamente. Deberas ver aDoctrinecomo una herramienta para sincronizar tus objetos en memoria con la base de

    datos en unidades de trabajo bien definidas. Trabajas con tus objetos y los modificas, como de costumbre y cuando

    termines llamas a EntityManager#flush()para persistir tus cambios.

    La unidad de trabajo

    Internamente un EntityManager utiliza una UnitOfWork, la cual es una tpica implementacin delpatrn unidad

    de trabajo, para realizar un seguimiento de todas las cosas que hay que hacer la prxima vez que invoques aflush.

    Por lo general, no interactas directamente con una UnitOfWorksino con el EntityManageren su lugar.

    1.3 Configurando

    1.3.1 Proceso de arranque

    El arranque deDoctrinees un procedimiento relativamente sencillo que consta ms o menos de tan slo 2 pasos:

    Se asegura de que los archivos de clase deDoctrinese pueden cargar bajo demanda.

    Obtiene una instancia del EntityManager.

    Carga de clase

    Vamos a empezar con la configuracin de la carga de clases. Tenemos que configurar algn cargador de clases (a

    menudo llamado autocargador) para que los archivos de las clases de Doctrinese carguen bajo demanda. El espacio

    de nombres Doctrine contiene un cargador de clases minimalista muy rpido y se puede utilizar para Doctrine y

    cualquier otra biblioteca, donde los estndares de codificacin garantizan que la ubicacin de una clase en el rbol de

    directorios se refleja en su nombre y espacio de nombres y donde hay un espacio de nombres raz comn.

    8 Captulo 1. Gua de referencia

    http://martinfowler.com/eaaCatalog/unitOfWork.htmlhttp://martinfowler.com/eaaCatalog/unitOfWork.htmlhttp://martinfowler.com/eaaCatalog/unitOfWork.htmlhttp://martinfowler.com/eaaCatalog/unitOfWork.html
  • 5/20/2018 Doctrine 2 Orm

    13/239

    Doctrine 2 ORM Documentation, Release 2.1

    Nota: No ests obligado a utilizar el cargador de clases deDoctrinepara cargar las clases de Doctrine. A Doctrineno

    le importa cmo se cargan las clases, si quieres usar un gestor de clases o cargar las clases de Doctrinet mismo, slo

    hazlo. En la misma lnea, el cargador de clases del espacio de nombres de Doctrineno est destinado a utilizarse para

    las clases de Doctrine, tampoco. Se trata de un cargador de clases genrico que puedes utilizar para cualquier clase

    que siga algunas normas de nomenclatura bsicas descritas anteriormente.

    El siguiente ejemplo muestra la configuracin de un cargador de clases para los diferentes tipos de instalaciones deDoctrine:

    Nota: Este asume que has creado algn tipo de guin para probar el siguiente cdigo con l. Algo as como un archivo

    test.php.

    Descarga PEAR o Tarball

  • 5/20/2018 Doctrine 2 Orm

    14/239

    Doctrine 2 ORM Documentation, Release 2.1

    $classloader = new \Doctrine\Common\ClassLoader(Symfony, $lib . vendor/);

    $classloader->register();

    Para un mejor rendimiento de la carga de clases, es recomendable que mantengas corto tu include_path, lo ideal es

    que slo debe contener la ruta a las bibliotecas de PEAR, y cualquier otra clase de biblioteca se debe registrar con su

    ruta base completa.

    Obteniendo un EntityManager

    Una vez que hayas preparado la carga de clases, adquiere una instancia delEntityManager. La claseEntityMana-

    geres el principal punto de acceso a la funcionalidad proporcionada por el ORM de Doctrine.

    Una configuracin simple del EntityManager requiere una instancia de Doctrine\ORM\Configuration,

    as como algunos parmetros de conexin para la base de datos:

  • 5/20/2018 Doctrine 2 Orm

    15/239

    Doctrine 2 ORM Documentation, Release 2.1

    1.3.2 Opciones de configuracin

    En las siguientes secciones se describen todas las opciones de configuracin disponibles en una instancia de

    Doctrine\ORM\Configuration.

    Directorio delegado (*REQUERIDO*)

  • 5/20/2018 Doctrine 2 Orm

    16/239

    Doctrine 2 ORM Documentation, Release 2.1

    La informacin de la ruta a las entidades es necesaria para la anotacin controlador, porque de lo contrario las opera-

    ciones masivas en todas las entidades a travs de la consola no funcionaran correctamente. Todos los controladores

    de metadatos aceptan tanto un solo directorio, como una cadena o una matriz de directorios. Con esta caracterstica un

    solo controlador puede dar soporte a mltiples directorios de entidades.

    Cach de metadatos (*RECOMENDADO*)

  • 5/20/2018 Doctrine 2 Orm

    17/239

    Doctrine 2 ORM Documentation, Release 2.1

  • 5/20/2018 Doctrine 2 Orm

    18/239

    Doctrine 2 ORM Documentation, Release 2.1

    Refiriendo delegados

    El mtodo EntityManager#getReference($nombreEntidad, $identificador) te permite obtener

    una referencia a una entidad para la cual se conoce el identificador, sin tener que cargar esa entidad desde la base

    de datos. Esto es til, por ejemplo, como una mejora de rendimiento, cuando deseas establecer una asociacin a una

    entidad para la cual tienes el mismo identificador. Slo tienes que hacer lo siguiente:

  • 5/20/2018 Doctrine 2 Orm

    19/239

    Doctrine 2 ORM Documentation, Release 2.1

    agregando estos controladores basados en el espacio de nombres:

  • 5/20/2018 Doctrine 2 Orm

    20/239

    Doctrine 2 ORM Documentation, Release 2.1

    .

    1.4.3 Asignando

    Por qu obtengo excepciones sobre restriccin de fallo nico en $em->flush()?

    Doctrine no comprueba si ests volviendo a agregar entidades con una clave primaria que ya existe o aadiendo

    entidades a una coleccin en dos ocasiones. Tienes que comprobar t mismo las condiciones en el cdigo antes de

    llamar a$em->flush()si sabes que puede ocurrir un fallo en la restriccin UNIQUE.

    InSymfony 2for example there is a Unique Entity Validator to achieve this task.

    Para colecciones puedes comprobar si una entidad ya es parte de esa coleccin con

    $collection->contains($entidad). Para una coleccin FETCH=LAZY esto inicia la coleccin, sin

    embargo, para FETCH=EXTRA_LAZY este mtodo utiliza SQL para determinar si esta entidad ya es parte de la

    coleccin.

    1.4.4 Asociaciones

    Qu est mal cuando me sale un InvalidArgumentExceptionSe encontr una nueva entidad en larelacin...?

    Esta excepcin se produce durante elEntityManager#flush()cuando existe un objeto en el mapa de identidad

    que contiene una referencia a un objeto del cual Doctrineno sabe nada. Digamos por ejemplo que tomas una entidad

    Usuario desde la base de datos con un id especfico y estableces un objeto completamente nuevo en una de las

    asociaciones del objeto Usuario. Si a continuacin, llamas a EntityManager#flush() sin dejar que Doctrine

    sepa acerca de este nuevo objeto conEntityManager#persist($nuevoObjeto)vers esta excepcin.

    Puedes resolver esta excepcin:

    Llamando aEntityManager#persist($nuevoObjeto)en el nuevo objeto

    Usarcascade=persisten la asociacin que contiene el nuevo objeto

    Cmo puedo filtrar una asociacin?

    Nativamente no puedes filtrar asociaciones en 2.0 y 2.1. Debes utilizar las consultas DQL para conseguir filtrar el

    conjunto de entidades.

    Llamo aclear()en una coleccin Uno-A-Muchos, pero no se eliminan las entidades

    Este es un comportamiento que tiene que ver con el lado inverso/propietario del controlador de Doctrine. Por defini-

    cin, una asociacin uno-a-muchos est en el lado inverso, es decir los cambios a la misma no sern reconocidos por

    Doctrine.Si deseas realizar el equivalente de la operacin de borrado tienes que recorrer la coleccin y fijar a NULL la referencia

    a la parte propietaria de muchos-a-uno para separar todas las entidades de la coleccin. Esto lanzar las declaraciones

    UPDATEadecuadas en la base de datos.

    16 Captulo 1. Gua de referencia

    http://www.symfony.com/http://www.symfony.com/
  • 5/20/2018 Doctrine 2 Orm

    21/239

    Doctrine 2 ORM Documentation, Release 2.1

    Cmo puedo agregar columnas a una tabla con relacin Muchos-A-Muchos?

    La asociacin muchos-a-muchos slo es compatible con claves externas en la definicin de la tabla, para trabajar con

    tablas muchos-a-muchos que contienen columnas adicionales, tienes que utilizar la caracterstica de claves externas

    como clave primaria de Doctrineintroducida en la versin 2.1.

    Ve lagua de claves primarias compuestaspara ms informacin.

    Cmo puedo paginar colecciones recuperadas desde uniones?

    Si ests emitiendo una declaracinDQLque recupera una coleccin, tampoco es fcil iterar sobre la coleccin usando

    una declaracinLIMIT(o equivalente del proveedor).

    Doctrineno ofrece una solucin para esto fuera de la caja, pero hay varias extensiones que lo hacen:

    Extensiones de Doctrine

    Pagerfanta

    Por qu no funciona correctamente la paginacin en uniones recuperadas?

    La paginacin enDoctrineutiliza una clusula LIMIT(o su equivalente del proveedor) para restringir los resultados.

    Sin embargo, al recuperar uniones estas no devuelven el nmero de resultados correcto debido a que se uni con

    una asociacin uno-a-muchos o muchos-a-muchos y esta multiplica el nmero de filas por el nmero de entidades

    asociadas.

    Ve la pregunta anterior para una solucin a esta tarea.

    1.4.5 Herencia

    Puedo utilizar herencia conDoctrine2?

    Si, enDoctrine2, puedes utilizar herencia simple o niendo tablas.

    Ve la documentacin en el captulo sobre la :doc:asignacin de herencia para ms detalles.

    Por quDoctrineno crea objetos delegados de la jerarqua de mi herencia?

    Si estableces una asociacin muchos-a-uno o uno-a-uno entre entidad y destino a cualquier clase padre de una herencia

    jerrquicaDoctrineen realidad no sabe qu clase PHP es la externa. Para averiguarlo tienes que ejecutar una consulta

    SQLpara buscar esta informacin en la base de datos.

    1.4.6 EntityGenerator

    Por qu el EntityGeneratorno hace X?

    The EntityGenerator is not a full fledged code-generator that solves all tasks. Code-Generation is not a first-class

    priority in Doctrine 2 anymore (compared to Doctrine 1). The EntityGenerator is supposed to kick-start you, but not

    towards 100 %.

    1.4. Preguntas ms frecuentes 17

    http://github.com/beberlei/DoctrineExtensionshttp://github.com/whiteoctober/pagerfantahttp://github.com/whiteoctober/pagerfantahttp://github.com/beberlei/DoctrineExtensions
  • 5/20/2018 Doctrine 2 Orm

    22/239

    Doctrine 2 ORM Documentation, Release 2.1

    Por qu el EntityGeneratorno genera la herencia correctamente?

    Just from the details of the discriminator map the EntityGenerator cannot guess the inheritance hierachy. This is why

    the generation of inherited entities does not fully work. You have to adjust some additional code to get this one working

    correctly.

    1.4.7 Rendimiento

    Por qu se ejecuta una consulta SQLextra cada vez que recupero una entidad con una relacinUno-A-Uno?

    SiDoctrinedetecta que ests recuperando un lado inverso de una asociacin uno-a-uno tiene que ejecutar una consulta

    adicional para cargar este objeto, porque no puede saber si no hay tal objeto (valor nulo) o si debe configurar un

    delegado cuyoidsea este delegado.

    Para resolver este problema actualmente tienes que ejecutar una consulta para buscar esta informacin.

    1.4.8 Lenguaje de consultaDoctrineQu esDQL?

    DQL (por Doctrine Query Language) es el lenguaje de consultas de Doctrine, un lenguaje de consultas que se parece

    mucho aSQL, pero tienes algunas ventajas importantes cuando utilizas Doctrine:

    It uses class names and fields instead of tables and columns, separating concerns between backend and your

    object model.

    It utilizes the metadata defined to offer a range of shortcuts when writing. Por ejemplo, no es necesario que

    especifiques la clusulaONde las uniones, ya que Doctrineya las conoce.

    It adds some functionality that is related to object management and transforms them into SQL.

    Tambin tiene algunos inconvenientes, por supuesto:

    The syntax is slightly different to SQL so you have to learn and remember the differences.

    To be vendor independent it can only implement a subset of all the existing SQL dialects. La funcionalidad

    especfica y optimizacin del proveedor no se pueden utilizar a travs de DQLa menos que la implementes

    explcitamente.

    For some DQL constructs subselects are used which are known to be slow in MySQL.

    Puedo ordenar por una funcin (por ejemplo ORDEN BY RAND()) en DQL?

    No, DQL no es compatible con la ordenacin en funciones. Si necesitas esta funcionalidad debes usar una consulta

    nativa o pensar en otra solucin. Como nota al margen: La ordenacin con ORDER BY RAND()es muy lenta a partir

    de 1000 filas.

    1.5 Asignacin bsica

    En este captulo se explica la asignacin bsica de objetos y propiedades. La asignacin de las asociaciones se tratar

    en el prximo captulo Asignando asociaciones.

    18 Captulo 1. Gua de referencia

  • 5/20/2018 Doctrine 2 Orm

    23/239

    Doctrine 2 ORM Documentation, Release 2.1

    1.5.1 Controladores de asignacin

    Doctrineproporciona varias maneras diferentes para especificar la asignacin de metadatos objetorelacional:

    AnotacionesDocblock

    XML

    YAML

    En este manual solemos hacer mencin de las anotaciones en los bloques de documentacin en todos los ejemplos

    dispersos a lo largo de todos los captulos, sin embargo, tambin se dan ejemplos alternativos para YAML y XML.

    Hay captulos de referencia dedicados para la asignacin XML y YAML, respectivamente, que los explican con ms

    detalle. Tambin hay un captulo de referencia para las anotaciones.

    Nota: Si te ests preguntando qu controlador de asignacin ofrece el mejor rendimiento, la respuesta es: todos dan

    exactamente el mismo rendimiento. Una vez que has ledo los metadatos de una clase desde la fuente (anotaciones,

    XML o YAML) se almacenan en una instancia de la clase Doctrine\ORM\Mapping\ClassMetadata y sus

    instancias se almacenan en la memoria cach de metadatos. Por lo tanto al final del da todos los controladores lo

    realizan igual de bien. Si no ests utilizando una memoria cach de metadatos (no se recomienda!), entonces el

    controlador XML podra tener una ligera ventaja en el rendimiento debido al potente soporte nativo XML de PHP.

    1.5.2 Introduccin a las anotacionesDocblock

    Probablemente ya hayas utilizado las anotaciones Docblock de alguna forma, muy probablemente proporcionando

    documentacin de metadatos a una herramienta como PHPDocumentor(@author, @link, ...). Las anotaciones doc-

    blockson una herramienta para incrustar metadatos dentro de la seccin de documentacin que luego, alguna he-

    rramienta puede procesar. Doctrine2 generaliza el concepto de anotaciones docblockpara que se puedan utilizar en

    cualquier tipo de metadatos y as facilitar la definicin de nuevas anotaciones docblock. A fin de implicar mas los

    valores de anotacin y para reducir las posibilidades de enfrentamiento con las anotaciones de docblock, las anotacio-

    nes docblockde Doctrine2 cuentan con una sintaxis alternativa que est fuertemente inspirada en la sintaxis de las

    anotaciones introducidas en Java 5.

    La implementacin de estas anotaciones docblock mejoradas se encuentran en el espacio de nombres

    Doctrine\Common\Annotations y por lo tanto, son parte del paquete Comn. Las anotaciones docblockde

    Doctrine2 cuentan con apoyo para espacios de nombres y anotaciones anidadas, entre otras cosas. El ORM de Doc-

    trine2 define su propio conjunto de anotaciones docblockpara suministrar asignacin de metadatos objetorelacional.

    Nota: Si no te sientes cmodo con el concepto de las anotaciones docblock, no te preocupes, como se mencion

    anteriormenteDoctrine2 ofrece alternativas XML y YAML y fcilmente podras implementar tu propio mecanismo

    preferido para la definicin de los metadatos del ORM.

    1.5.3 Clases persistentes

    Con el fin de marcar una clase para persistencia objetorelacional la debes designar como una entidad. Esto se puede

    hacer a travs de la anotacin@Entity.

    PHP

  • 5/20/2018 Doctrine 2 Orm

    24/239

    Doctrine 2 ORM Documentation, Release 2.1

    //...}

    XML

    YAML

    MyPersistentClass:

    type: entity

    # ...

    De manera predeterminada, la entidad ser persistida en una tabla con el mismo nombre que el nombre de la clase. A

    fin de cambiar esta situacin, puedes utilizar la anotacin @Tablede la siguiente manera:

    PHP

  • 5/20/2018 Doctrine 2 Orm

    25/239

    Doctrine 2 ORM Documentation, Release 2.1

    string: Tipo que asigna unVARCHAR SQLa una cadena PHP.

    integer: Tipo que asigna un INT SQLa un entero de PHP.

    smallint: Tipo que asigna un SMALLINTde la base de datos a un entero de PHP.

    bigint: Tipo que asigna unBIGINTde la base de datos a una cadena de PHP.

    boolean: Tipo que asigna un valorbooleano SQLa unbooleanode PHP.

    decimal: Tipo que asigna un DECIMAL SQLa un doble dePHP.

    date: Tipo que asigna unDATETIMEde SQLa un objeto DateTimede PHP.

    time: Tipo que asigna unTIMEde SQL a un objeto DateTimede PHP.

    datetime: Tipo que asigna un DATETIME/TIMESTAMP SQLa un objeto DateTimede PHP.

    text: Tipo que asigna unCLOB SQLa una cadena de PHP.

    object: Tipo que asigna unCLOB SQLa un objeto dePHP usandoserialize()y unserialize()

    array: Tipo que asigna unCLOB SQLa un objeto dePHP usandoserialize()y unserialize()

    float: Tipo que se asigna un Float SQL (de doble precisin) en un double de PHP. IMPORTANTE: Slo

    funciona con opciones regionales que utilizan punto decimal como separador.

    Nota: Tipos de asignacin de DoctrineNO son tiposSQL y NO son tipos de PHP! Son tipos de asignacin entre 2

    tipos. Adems los tipos de asignacin susceptibles a maysculas y minsculas. Por ejemplo, al utilizar una columna

    DateTimeno coincidir con el tipodatetimesuministrado conDoctrine2.

    Nota: DateTime and Object types are compared by reference, not by value. Doctrine updates this values if the refe-

    rence changes and therefore behaves as if these objects are immutable value objects.

    Advertencia: Todos los tipos de fecha asumen que se est utilizando exclusivamente la zona horaria establecida

    por date_default_timezone_set() o por la configuracin date.timezone de php.ini. Trabajar con diferentes

    zonas horarias causar problemas y un comportamiento inesperado.

    Si necesitas manejar zonas horarias especficas que tienen que manejar esto en tu dominio, convierte todos los

    valores a UTC de ida y vuelta. Tambin hay un artculo en el recetariosobre el trabajo con fechas y horas que

    proporciona consejos para implementar aplicaciones de mltiples zonas horarias.

    1.5.5 Asignando propiedades

    Despus de marcar una clase como una entidad esta puede especificar las asignaciones para los campos de su ins-

    tancia. Aqu slo nos fijaremos en los campos simples que tienen valores escalares como cadenas, nmeros, etc. Las

    asociaciones con otros objetos se tratan en el captulo Asignando asociaciones.

    Para marcar una propiedad para persistencia relacional se utiliza la anotacin docblock @Column. Esta anotacingeneralmente requiere fijar por lo menos un atributo, el type. El atributo typeespecifica el tipo de asignacin que

    Doctrineusar para el campo. Si no se especifica el tipo, se usa stringcomo el tipo de asignacin por omisin, ya

    que es el ms flexible.

    Ejemplo:

    PHP

    1.5. Asignacin bsica 21

    http://docs.php.net/manual/es/function.date-default-timezone-set.phphttp://docs.php.net/manual/es/function.date-default-timezone-set.php
  • 5/20/2018 Doctrine 2 Orm

    26/239

    Doctrine 2 ORM Documentation, Release 2.1

  • 5/20/2018 Doctrine 2 Orm

    27/239

    Doctrine 2 ORM Documentation, Release 2.1

    name: (opcional, predeterminado al nombre del campo) El nombre de la columna en la base de datos.

    length: (opcional, predeterminado a 255) La longitud de la columna en la base de datos. (Slo se aplica si se

    usa un valor de cadena en la columna).

    unique: (opcional, predeterminado aFALSE) Si la columna es una clave nica.

    nullable: (opcional, predeterminado aFALSE) Si la columna de la base de datos acepta valores nulos.

    precision: (opcional, predeterminado a 0) La precisin para una columna decimal (numrica exacta). (Slo

    aplica si se usa una columna decimal.)

    scale: (opcional, predeterminado a 0) La escala para una columna decimal (numrica exacta). (Slo aplica si

    se usa una columna decimal.)

    1.5.6 Tipos de asignacin personalizados

    Doctrinete permite crear nuevos tipos de asignacin. Esto puede ser til cuando ests perdiendo un tipo de asignacin

    especfico o cuando deseas reemplazar la aplicacin actual de un tipo de asignacin.

    A fin de crear un nuevo tipo de asignacin necesitas una subclase de Doctrine\DBAL\Types\Type e implemen-

    tar/redefinir los mtodos a tu gusto. Aqu est un esqueleto de ejemplo de una clase de tipo personalizada:

  • 5/20/2018 Doctrine 2 Orm

    28/239

    Doctrine 2 ORM Documentation, Release 2.1

    LaUnitOfWorknunca pasa los valores de la base de datos que no han cambiado al mtodo convertir.

    Cuando has implementado el tipo todava tienes que notificar su existencia a Doctrine. Esto se puede lograr a travs

    del mtodoDoctrine\DBAL\Types\Type#addType($nombre, $className). Ve el siguiente ejemplo:

  • 5/20/2018 Doctrine 2 Orm

    29/239

    Doctrine 2 ORM Documentation, Release 2.1

  • 5/20/2018 Doctrine 2 Orm

    30/239

    Doctrine 2 ORM Documentation, Release 2.1

    MyPersistentClass:

    type: entity

    id:

    id:

    type: integer

    generator:

    strategy: AUTOfields:

    name:

    length: 50

    Esto le dice aDoctrineque genere automticamente un valor para el identificador. Cmo se genera este valor se especi-

    fica mediante la estrategia de atributo, que es opcional y por omisin esAUTO. Un valor deAUTOdice aDoctrine

    que utilice la estrategia de generacin que es preferida por la plataforma de base de datos utilizada actualmente. Ve

    ms adelante para obtener ms detalles.

    Estrategias para la generacin de identificador

    El ejemplo anterior muestra cmo utilizar la estrategia de generacin de identificador predeterminada sin conocer la

    base de datos subyacente con la estrategia de deteccin automtica. Tambin es posible especificar la estrategia degeneracin de identificador de manera ms explcita, lo cual te permite usar algunas caractersticas adicionales.

    Aqu est la lista de posibles estrategias de generacin:

    AUTO (predeterminada): Le dice aDoctrineque escoja la estrategia preferida por la plataforma de base de datos.

    Las estrategias preferidas son la IDENTIDAD de MySQL, SQLite y MsSQL y las SECUENCIA de Oracle y

    PostgreSQL. Esta estrategia ofrece una portabilidad completa.

    SEQUENCE: Le dice a Doctrineque use una secuencia de la base de datos para gestionar elID. Esta estrategia

    actualmente no proporciona portabilidad total. Las secuencias son compatibles con Oracle y PostgreSQL.

    IDENTITY: Le dice a Doctrine que use una columna de identidad especial en la base de datos que genere

    un valor o inserte una fila. Esta estrategia actualmente no proporciona una total portabilidad y es compatible

    con las siguientes plataformas: MySQL/SQLite (AUTO_INCREMENT), MSSQL (IDENTIDAD) y PostgreSQL

    (SERIAL).

    TABLE: Le dice a Doctrineque use una tabla independiente para la generacin del ID. Esta estrategia ofrece

    una portabilidad completa.*Esta estrategia an no est implementada*

    NONE: Indica a Doctrine que los identificadores son asignados (y por lo tanto generados) por tu cdigo. La

    asignacin tendr lugar antes de pasar una nueva entidad a EntityManager#persist.NONEes lo mismo

    que dejar fuera a @GeneratedValuepor completo.

    Generador de secuencia

    El generador de secuencias actualmente se puede utilizar en conjunto con Oracle o Postgres y permite algunas opciones

    de configuracin adicionales, adems de especificar el nombre de la secuencia:PHP

  • 5/20/2018 Doctrine 2 Orm

    31/239

    Doctrine 2 ORM Documentation, Release 2.1

    */protected $id = null;

    }

    XML

  • 5/20/2018 Doctrine 2 Orm

    32/239

    Doctrine 2 ORM Documentation, Release 2.1

    Para designar un identificador/clave primaria compuesta, simplemente coloca la anotacin @Id en todos los campos

    que componen la clave primaria.

    1.5.9 Citando palabras reservadas

    Posiblemente en ocasiones necesites citar un nombre de columna o tabla porque est en conflicto con una palabrareservada para el uso del RDBMSparticular. Esto se refiere a menudo como Citando identificadores. Para permitir

    queDoctrinesepa como te gustara un nombre de tabla o columna tienes que citarlo en todas las declaracionesSQL,

    escribe el nombre de la tabla o columna entre acentos abiertos. Aqu est un ejemplo:

  • 5/20/2018 Doctrine 2 Orm

    33/239

    Doctrine 2 ORM Documentation, Release 2.1

    El lado muchos relaciones bidireccionales OneToMany/ManyToOne debeser la parte propietaria, por lo tanto,

    el elementomappedByno se puede especificar en el lado ManyToOne.

    Para relaciones bidireccionales OneToOne, la parte propietaria concuerda a la parte que contiene la clave

    externa correspondiente (@JoinColumn(s)).

    Para relaciones bidireccionales ManyToManycualquiera puede ser el lado propietario (la parte que define el

    @JoinTabley/o no usa el atributo mappedBy, utilizando as una lnea predeterminada de unin de tabla).

    Especialmente importante es la siguiente:

    El lado propietario de una relacin determina las actualizaciones a la relacin en la base de datos.

    Para comprender esto, recuerda cmo se mantienen las asociaciones bidireccionales en el mundo de los objetos. Hay

    dos referencias a cada lado de la asociacin y las dos referencias de ambos representan la misma asociacin, pero

    puede cambiar de forma independiente la una de la otra. Por supuesto, en una correcta aplicacin de la semntica,

    las asociaciones bidireccionales son mantenidas adecuadamente por el desarrollador de la aplicacin (porque es su

    responsabilidad).Doctrinetiene que saber cul de estas dos referencias en memoria es la que se debe conservar y cul

    no. Esto es para lo que se utiliza el concepto propietario/inverso principalmente.

    **Los cambios realizados slo en el lado inverso de la asociacin son ignorados. Asegrate de actualizar ambos lados

    de una asociacin bidireccional (o al menos el lado propietario, desde el punto de vista de Doctrine) **

    El lado propietario de una asociacin bidireccional es el lado en que buscaDoctrinea la hora de determinar el estado

    de la asociacin, y por lo tanto si hay algo que hacer para actualizar la asociacin en la base de datos.

    Nota: El lado propietario y el lado inverso son conceptos tcnicos de la tecnologa ORM, no conceptos de tu

    modelo del dominio. Lo que consideras como el lado propietario en tu modelo del dominio puede ser diferente al lado

    propietario deDoctrine. Estos no estn relacionados.

    1.6.2 Colecciones

    En todos los ejemplos de los muchos valores de las asociaciones en este manual usaremos una interfaz de Coleccin

    y una implementacin predeterminada correspondiente ArrayCollection que se definen en el espacio de nombresDoctrine\Common\Collections. Por qu necesitamos esto? Qu no es la pareja de mi modelo del dominio

    paraDoctrine? Desafortunadamente, las matrices de PHP, si bien son buenas para muchas cosas, no se constituyen

    buenas para colecciones de objetos del negocio, especialmente no en el contexto de un ORM. La razn es que los

    arreglos planos de PHP no se pueden ampliar/instrumentar transparentemente en el cdigo PHP, lo cual es necesario

    para un montn de caractersticas avanzadas del ORM. Las clases/interfaces que se acercan ms a una coleccin OO

    (Orientada a Objetos) son ArrayAccessy ArrayObjectpero hasta que creas instancias de este tipo se pueden

    utilizar en todos los lugares donde se puede utilizar una matriz plana (algo que puede suceder en PHP*6) su utilidad

    es bastante limitada. Puedes sugerir el tipo ArrayAccess en vez de la Coleccin, ya que la interfaz de la

    Coleccin extiende a ArrayAccess, pero esto te limitar severamente en la forma en que puedes trabajar con la

    Coleccin, ya que la *APIde ArrayAccess (intencionalmente) es muy primitiva y es ms importante porque no

    puedes pasar a esta Coleccin todas las funciones tiles de los arreglos PHP, lo cual dificulta trabajar con l.

    Advertencia: La interfaz de Coleccin y la claseArrayCollection, como todo lo dems en el espacio denombres deDoctrine, no son parte del ORM, ni de DBAL, se trata de una clase PHP simple que no tiene ninguna

    dependencia externa, aparte de las dependencias de PHP en s mismo (y SPL). Por lo tanto, con esta clase en las

    clases de tu dominio y en otros lugares no introduce un acoplamiento a la capa de persistencia. La clase Coleccin,

    como todo lo dems en el espacio de nombres Comn, no es parte de la capa de persistencia. Incluso puedes copiar

    la clase a tu proyecto si deseas eliminar Doctrinede tu proyecto y todas las clases del dominio funcionarn igual

    que antes.

    1.6. Asignando asociaciones 29

  • 5/20/2018 Doctrine 2 Orm

    34/239

    Doctrine 2 ORM Documentation, Release 2.1

    1.6.3 Asignacin predeterminada

    Antes de presentar todas las asignaciones de asociaciones en detalle, debes tener en cuenta que las definiciones

    @JoinColumn y @JoinTable suelen ser opcionales y tienen valores predeterminados razonables. Los valores

    predeterminados para una columna en una unin de asociacin uno-a-uno/muchos-a-uno son los siguientes:

    name: "_id"

    referencedColumnName: "id"

    Como ejemplo, considera esta asignacin:

    PHP

  • 5/20/2018 Doctrine 2 Orm

    35/239

    Doctrine 2 ORM Documentation, Release 2.1

    joinColumn:

    name: shipping_id

    referencedColumnName: id

    La definicin @JoinTable utilizada para asignaciones muchos-a-muchos tiene predeterminados similares. Como

    ejemplo, considera esta asignacin:

    PHP

  • 5/20/2018 Doctrine 2 Orm

    36/239

    Doctrine 2 ORM Documentation, Release 2.1

    YAML

    User:

    type: entity

    manyToMany:

    groups:

    targetEntity: Group

    joinTable:

    name: User_Group

    joinColumns:

    User_id:

    referencedColumnName: id

    inverseJoinColumns:

    Group_id

    referencedColumnName: id

    En ese caso, el nombre de la tabla predeterminada est unida a una combinacin simple, del nombre de clase sin

    calificar de las clases participantes, separadas por un carcter de subrayado. Los nombres de las columnas de la

    unin por omisin al nombre simple, del nombre de la clase din calificar a la clase destino, seguido de \_id. El

    referencedColumnName de manera predeterminada siempre a id, al igual que en asignaciones uno-a-uno o

    muchos-a-uno.

    Si aceptas estos valores predeterminados, puedes reducir al mnimo tu cdigo de asignacin.

    1.6.4 Iniciando ColeccionesTienes que tener cuidado al utilizar los campos de entidad que contienen una coleccin de entidades relacionadas.

    Digamos que tenemos una entidad Usuario que contiene una coleccin de Grupos:

  • 5/20/2018 Doctrine 2 Orm

    37/239

    Doctrine 2 ORM Documentation, Release 2.1

  • 5/20/2018 Doctrine 2 Orm

    38/239

    Doctrine 2 ORM Documentation, Release 2.1

    (como en las definiciones de asignacin), tienes que quitar la barra inversa prefija. PHP hace esto con get_class()

    o mtodos de reflexin por razones de compatibilidad hacia atrs.

    1.6.6 Uno-A-Uno, unidireccional

    A asociacin unidireccional uno-a-uno es muy comn. He aqu un ejemplo de un Productoque tiene asociado un

    objetoEnvo. El ladoEnvono hace referencia de nuevo alProductopor lo tanto es unidireccional.

    PHP

  • 5/20/2018 Doctrine 2 Orm

    39/239

    Doctrine 2 ORM Documentation, Release 2.1

    CREATE TABLE Product (

    id INT AUTO_INCREMENT NOT NULL,

    shipping_id INT DEFAULT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    CREATE TABLE Shipping (

    id INT AUTO_INCREMENT NOT NULL,PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    ALTER TABLE Product ADD FOREIGN KEY (shipping_id) REFERENCES Shipping(id);

    1.6.7 Uno-A-Uno, bidireccional

    Aqu hay una relacin uno-a-uno bidireccional entre un Clientey un Carrito. El Carritotiene una referencia

    alClientepor lo tanto es bidireccional.

    PHP

  • 5/20/2018 Doctrine 2 Orm

    40/239

    Doctrine 2 ORM Documentation, Release 2.1

    YAML

    Customer:

    oneToOne:

    cart:

    targetEntity: Cart

    mappedBy: customer

    Cart:

    oneToOne:

    customer:

    targetEntity Customer

    inversedBy: cart

    joinColumn:

    name: customer_id:

    referencedColumnName: id

    Ten en cuenta que la@JoinColumnrealmente no es necesaria en este ejemplo, puesto que con los valores predeter-

    minados sera lo mismo.

    Esquema MySQL generado:

    CREATE TABLE Cart (

    id INT AUTO_INCREMENT NOT NULL,

    customer_id INT DEFAULT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    CREATE TABLE Customer (

    id INT AUTO_INCREMENT NOT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    ALTER TABLE Cart ADD FOREIGN KEY (customer_id) REFERENCES Customer(id);

    Observa cmo la clave externa se define en el lado propietario de la relacin, la tabla Carrito.

    1.6.8 Uno-A-Uno, autoreferencia

    Puedes tener una referencia a s mismo en una relacin uno-a-uno como la siguiente.

  • 5/20/2018 Doctrine 2 Orm

    41/239

    Doctrine 2 ORM Documentation, Release 2.1

    CREATE TABLE Student (

    id INT AUTO_INCREMENT NOT NULL,

    mentor_id INT DEFAULT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    ALTER TABLE Student ADD FOREIGN KEY (mentor_id) REFERENCES Student(id);

    1.6.9 Uno-A-Muchos, unidireccional con tablas unidas

    Puedes asignar una asociacin uno-a-muchos unidireccional a travs de una unin de tablas. Desde el punto de vista

    deDoctrine, simplemente es asignada como una muchos-a-muchos unidireccional por lo cual una restriccin nica en

    una de las columnas de la unin refuerza la cardinalidad de uno-a-muchos. El siguiente ejemplo, se configura tal como

    una asociacin unidireccional uno-a-muchos:

    Nota: Las relaciones uno-a-muchos unidireccionales con unin de tablas slo trabaja usando la anotacin

    @ManyToManyy una restriccin de unicidad.

    Genera el siguiente esquema MySQL:

    CREATE TABLE User (

    id INT AUTO_INCREMENT NOT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    CREATE TABLE users_phonenumbers (

    user_id INT NOT NULL,

    phonenumber_id INT NOT NULL,

    UNIQUE INDEX users_phonenumbers_phonenumber_id_uniq (phonenumber_id),

    PRIMARY KEY(user_id, phonenumber_id)

    ) ENGINE = InnoDB;

    CREATE TABLE Phonenumber (id INT AUTO_INCREMENT NOT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    ALTER TABLE users_phonenumbers ADD FOREIGN KEY (user_id) REFERENCES User(id);

    ALTER TABLE users_phonenumbers ADD FOREIGN KEY (phonenumber_id) REFERENCES Phonenumber(id);

    1.6.10 Muchos-A-Uno, unidireccional

    Fcilmente puedes implementar una asociacin unidireccional muchos-a-uno con lo siguiente:

    PHP

  • 5/20/2018 Doctrine 2 Orm

    42/239

    Doctrine 2 ORM Documentation, Release 2.1

    */private $address;

    }

    /** @Entity */class Address

    { // ...}

    XML

    YAML

    User:

    type: entitymanyToOne:

    address:

    targetEntity: Address

    Nota: La @JoinColumn anterior es opcional ya que por omisin siempre son address_id e id. Los puedes

    omitir y dejar que se utilicen los valores predeterminados.

    Esquema MySQL generado:

    CREATE TABLE User (

    id INT AUTO_INCREMENT NOT NULL,

    address_id INT DEFAULT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    CREATE TABLE Address (

    id INT AUTO_INCREMENT NOT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    ALTER TABLE User ADD FOREIGN KEY (address_id) REFERENCES Address(id);

    1.6.11 Uno-A-Muchos, bidireccional

    Las asociaciones bidireccionales uno-a-muchos son muy comunes. El siguiente cdigo muestra un ejemplo con unaclaseProductoy Caractersticas:

    XML

    38 Captulo 1. Gua de referencia

  • 5/20/2018 Doctrine 2 Orm

    43/239

    Doctrine 2 ORM Documentation, Release 2.1

    Ten en cuenta que la@JoinColumnrealmente no es necesaria en este ejemplo, puesto que con los valores predeter-

    minados sera lo mismo.Esquema MySQL generado:

    CREATE TABLE Product (

    id INT AUTO_INCREMENT NOT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    CREATE TABLE Feature (

    id INT AUTO_INCREMENT NOT NULL,

    product_id INT DEFAULT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    ALTER TABLE Feature ADD FOREIGN KEY (product_id) REFERENCES Product(id);

    1.6.12 Uno-A-Muchos, con autoreferencia

    Tambin puedes configurar una asociacin uno-a-muchos con autoreferencia. En este ejemplo, configuramos una

    jerarqua de objetosCategora creando una relacin que hace referencia a s misma. Esto efectivamente modela

    una jerarqua de Categoras y desde la perspectiva de la base de datos se conoce como un enfoque de lista adyacente.

    PHP

  • 5/20/2018 Doctrine 2 Orm

    44/239

    Doctrine 2 ORM Documentation, Release 2.1

    YAML

    Category:

    type: entity

    oneToMany:

    children

    targetEntity: Category

    mappedBy: parent

    manyToOne:

    parent:

    targetEntity: Category

    inversedBy: children

    Ten en cuenta que la@JoinColumnrealmente no es necesaria en este ejemplo, puesto que con los valores predeter-

    minados sera lo mismo.

    Esquema MySQL generado:

    CREATE TABLE Category (id INT AUTO_INCREMENT NOT NULL,

    parent_id INT DEFAULT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    ALTER TABLE Category ADD FOREIGN KEY (parent_id) REFERENCES Category(id);

    1.6.13 Muchos-A-Muchos, unidireccional

    Las asociaciones de muchos-a-muchos reales son menos comunes. El siguiente ejemplo muestra una asociacin uni-

    direccional entre las entidades Usuario y Grupo:

    PHP

  • 5/20/2018 Doctrine 2 Orm

    45/239

    Doctrine 2 ORM Documentation, Release 2.1

    class Group

    {

    // ...}

    XML

    YAML

    User:

    type: entity

    manyToMany:

    groups:

    targetEntity: Group

    joinTable:

    name: users_groups

    joinColumns:

    user_id:

    referencedColumnName: id

    inverseJoinColumns:

    group_id:referencedColumnName: id

    Esquema MySQL generado:

    CREATE TABLE User (

    id INT AUTO_INCREMENT NOT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    CREATE TABLE users_groups (

    user_id INT NOT NULL,

    group_id INT NOT NULL,

    PRIMARY KEY(user_id, group_id)

    ) ENGINE = InnoDB;

    CREATE TABLE Group (id INT AUTO_INCREMENT NOT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    ALTER TABLE users_groups ADD FOREIGN KEY (user_id) REFERENCES User(id);

    ALTER TABLE users_groups ADD FOREIGN KEY (group_id) REFERENCES Group(id);

    Nota: Por qu muchos-a-muchos son menos comunes? Debido a que frecuentemente deseas relacionar atributos

    adicionales con una asociacin, en cuyo caso introduces una clase de asociacin. En consecuencia, la asociacin

    1.6. Asignando asociaciones 41

  • 5/20/2018 Doctrine 2 Orm

    46/239

    Doctrine 2 ORM Documentation, Release 2.1

    muchos-a-muchos directa desaparece y es reemplazada por las asociaciones uno-a-muchos/muchos-a-uno entre las

    tres clases participantes.

    1.6.14 Muchos-A-Muchos, bidireccional

    Aqu hay una relacin muchos-a-muchos similar a la anterior, salvo que esta es bidireccional.

    PHP

  • 5/20/2018 Doctrine 2 Orm

    47/239

    Doctrine 2 ORM Documentation, Release 2.1

    YAML

    User:

    type: entity

    manyToMany:

    groups:

    targetEntity: Group

    inversedBy: users

    joinTable:

    name: users_groups

    joinColumns:

    user_id:

    referencedColumnName: id

    inverseJoinColumns:

    group_id:

    referencedColumnName: id

    Group:

    type: entity

    manyToMany:

    users:

    targetEntity: User

    mappedBy: groups

    El esquema MySQL es exactamente el mismo que para el caso muchos-a-muchos unidireccional anterior.

    Eligiendo el lado propietario o inverso

    Para asociaciones muchos-a-muchos puedes elegir cual entidad es la propietaria y cual el lado inverso. Hay una regla

    semntica muy simple para decidir de qu lado es ms adecuado el lado propietario desde la perspectiva de los desa-

    rrolladores. Slo tienes que preguntarte, qu entidad es la responsable de gestionar la conexin y seleccin, como la

    parte propietaria.

    Tomemos un ejemplo de dos entidades Artculoy Etiqueta. Cada vez que deseas conectar un Artculo a una

    Etiqueta y viceversa, sobre todo es el Artculo, el que es responsable de esta relacin. Cada vez que aades un nuevo

    Artculo, quieres conectarlo con Etiquetas existentes o nuevas. Probablemente si creas un formulario Artculo apoyes

    esta idea y te permita especificar las etiquetas directamente. Es por eso que debes escoger el Artculo como el lado

    propietario, ya que hace ms comprensible tu cdigo:

  • 5/20/2018 Doctrine 2 Orm

    48/239

    Doctrine 2 ORM Documentation, Release 2.1

    }

    }

    class Tag

    {

    private $articles;

    public function addArticle(Article $article)

    {

    $this->articles[] = $article;

    }

    }

    Esto permite agrupar la etiqueta aadindola en el lado Artculode la asociacin:

  • 5/20/2018 Doctrine 2 Orm

    49/239

    Doctrine 2 ORM Documentation, Release 2.1

    CREATE TABLE User (

    id INT AUTO_INCREMENT NOT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    CREATE TABLE friends (

    user_id INT NOT NULL,

    friend_user_id INT NOT NULL,PRIMARY KEY(user_id, friend_user_id)

    ) ENGINE = InnoDB;

    ALTER TABLE friends ADD FOREIGN KEY (user_id) REFERENCES User(id);

    ALTER TABLE friends ADD FOREIGN KEY (friend_user_id) REFERENCES User(id);

    1.6.16 Ordenando colecciones A-Muchos

    En muchos casos de uso desears ordenar colecciones cuando las recuperas de la base de datos. En el espacio de

    los usuarios lo haces, siempre y cuando inicialmente, no se haya guardado en la base de datos una entidad con sus

    asociaciones. Para recuperar una coleccin ordenada desde la base de datos puedes utilizar la anotacin @OrderBy

    con una coleccin que especifica un fragmentoDQLque se aade a todas las consultas con esta coleccin.

    Adicional a las anotaciones @OneToMany o @ManyToMany puedes especificar la anotacin @OrderBy de la si-guiente manera:

  • 5/20/2018 Doctrine 2 Orm

    50/239

    Doctrine 2 ORM Documentation, Release 2.1

    SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 ORDER BY g.name ASC

    No puedes invertir el orden con unaORDER BY DQLexplcita:

    SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 ORDER BY g.name DESC

    ...internamente se reescribe a:

    SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 ORDER BY g.name DESC, g.name ASC

    1.7 Asignando herencia

    1.7.1 Asignando superclases

    Una asignacin de superclase es una clase abstracta o concreta que proporciona estado persistente a la entidad y la

    informacin de asignacin de sus subclases, pero que en s misma no es una entidad. Por lo general, el propsito de

    esta superclase asignada es definir la informacin de estado y la asignacin que es comn a varias clases de entidades.

    Las superclases asignadas, as como regulares, no asignan las clases, pueden aparecer en medio de una jerarqua deherencia asignada de otro modo (a travs de la herencia de una sola tabla o de la herencia de tablas de clase).

    Nota: Una superclase asignada no puede ser una entidad, no es capaz de consultas y las relaciones persistentes las debe

    definir una superclase unidireccional asignada (con solamente un lado propietario). Esto significa que las asociaciones

    uno-a-muchos en una superclase asignada no son posibles en absoluto. Adems, asignaciones muchos-a-muchos slo

    son posibles si la superclase asignada slo utiliza exactamente una entidad al momento. Para mayor apoyo de herencia,

    las caractersticas de herencia tienes que usar una sola tabla o unin.

    Ejemplo:

  • 5/20/2018 Doctrine 2 Orm

    51/239

    Doctrine 2 ORM Documentation, Release 2.1

    // ... ms campos y mtodos}

    El DDL para el esquema de base de datos correspondiente se vera algo como esto (esto es para SQLite):

    CREATE TABLE EntitySubClass (mapped1 INTEGER NOT NULL, mapped2 TEXT NOT NULL, id INTEGER NO

    Como puedes ver en este fragmento DDL, slo hay una nica tabla de la subclase entidad. Todas las asignaciones de

    la superclase asignada fueron heredadas de la subclase como si se hubieran definido en dicha clase directamente.

    1.7.2 Herencia de una sola tabla

    Laherencia de tabla nicaes una estrategia de asignacin de herencias donde todas las clases de la jerarqua se asignan

    a una nica tabla de la base de datos. A fin de distinguir qu fila representa cual tipo en la jerarqua, se utiliza una as

    llamada columna discriminadora.

    Ejemplo:

  • 5/20/2018 Doctrine 2 Orm

    52/239

    Doctrine 2 ORM Documentation, Release 2.1

    aunque en grandes despliegues esto puede tener un impacto negativo en el ndice y diseo de la columna dentro de la

    base de datos.

    Impacto en el rendimiento

    Esta estrategia es muy eficaz para consultar todos los tipos de la jerarqua o para tipos especficos. No se requierenuniones de tablas, slo una clusula WHERE listando los identificadores de tipo. En particular, las relaciones que

    implican tipos que emplean esta estrategia de asignacin son de buen calidad.

    Hay una consideracin de rendimiento general, con herencia de tabla nica: si utilizas una entidad STI como muchos-

    a-uno o una entidad uno-a-uno nunca debes utilizar una de las clases en los niveles superiores de la jerarqua de

    herencia como "targetEntity" slo aquellas que no tienen subclases. De lo contrarioDoctrine NO PUEDEcrear

    instancias delegadas de esta entidad y SIEMPREdebe cargar la entidad impacientemente.

    Consideraciones del esquema SQL

    Una herencia de una sola tabla trabaja en escenarios en los que ests utilizando un esquema de base de datos existente

    o un esquema de base de datos autoescrito que tienes que asegurarte de que todas las columnas que no estn en la

    entidad raz, sino en cualquiera de las diferentes subentidades tiene que permite valores nulos. Las columnas que notienen restriccionesNULL, tienen que estar en la entidad raz de la jerarqua de herencia de una sola tabla.

    1.7.3 Herencia clasetabla

    Laherencia clasetablaes una estrategia de asignacin de herencias, donde se asigna cada clase en una jerarqua

    de varias tablas: su propia tabla y las tablas de todas las clases padre. La tabla de una clase hija est relacionada

    con la tabla de una clase padre a travs de una clave externa. Doctrine2 implementa esta estrategia a travs del uso

    de una columna discriminadora de la tabla superior de la jerarqua, porque es la forma ms fcil de lograr consultas

    polimrficas con herencia clasetabla.

    Ejemplo:

  • 5/20/2018 Doctrine 2 Orm

    53/239

    Doctrine 2 ORM Documentation, Release 2.1

    El @DiscriminatorMap especifica cuales valores de la columna discriminadora identifican una fila como

    de qu tipo. En el caso anterior un valor de persona, define una fila como de tipo Persona y empleado

    identifica una fila como de tipo Empleado.

    Los nombres de las clases en la asignacin discriminadora no tienen que estar completos si las clases estn con-

    tenidas en el mismo espacio de nombres como la clase entidad en la que se aplica la asignacin discriminadora.

    Nota: Cuando no utilices la SchemaTool para generar el cdigo SQL necesario debes saber que la supresin

    de una herencia de tablas de la clase utiliza la propiedad ON DELETE CASCADE de la clave externa en todas las

    implementaciones de bases de datos. Una falla al implementar esto t mismo dars lugar a filas muertas en la base de

    datos.

    Consideraciones en tiempo de diseo

    Introducir un nuevo tipo a la jerarqua, a cualquier nivel, implica simplemente intercalar una nueva tabla en el esquema.

    Los subtipos de este tipo se unirn automticamente con el nuevo tipo en tiempo de ejecucin. Del mismo modo, la

    modificacin de cualquier tipo de entidad en la jerarqua agregando, modificando o eliminando campos afecta slo

    a la tabla inmediata asignado ese tipo. Esta estrategia de asignacin proporciona la mayor flexibilidad en tiempo de

    diseo, ya que los cambios de cualquier tipo son siempre limitados al tipo dedicado de la tabla.

    Impacto en el rendimiento

    Esta estrategia inherentemente requiere mltiples operaciones JOINpara realizar cualquier consulta que pueda tener

    un impacto negativo en el rendimiento, especialmente con tablas de gran tamao y/o grandes jerarquas. Cuando los

    se permiten objetos parciales, ya sea globalmente o en la consulta especfica, entonces consultar por cualquier tipo

    no har que las tablas de los subtipos sean OUTER JOIN lo cual puede aumentar el rendimiento, pero los objetos

    parciales resultantes no se cargan completamente al acceder a los campos de cualquier subtipo, por lo que acceder a

    los campos de los subtipos despus de una consulta no es seguro.

    Hay una consideracin de rendimiento general, con la herencia de clases de tabla: si utilizas una entidad CTI como

    muchos-a-uno o una entidad uno-a-uno nunca debes utilizar una de las clases en los niveles superiores de la jerarquade herencia como "targetEntity", slo aquellas que no tienen subclases. De lo contrario Doctrine NO PUEDE

    crear instancias delegadas de esta entidad y SIEMPREdebe cargar la entidad impacientemente.

    Consideraciones del esquema SQL

    Para cada entidad en la jerarqua de herencia de clasetabla todos los campos asignados tienen que ser columnas en la

    tabla de esta entidad. Adems, cada tabla secundaria tiene que tener una columna idque concuerde con la definicin

    de la columna iden la tabla raz (a excepcin de alguna secuencia o detalles de autoincremento). Adems, cada tabla

    secundaria debe tener una clave externa apuntando desde la columna id a la columna id de la tabla raz y eliminacin

    en cascada.

    1.8 Trabajando con objetos

    Este captulo te ayudar a entender el EntityManagery laUnitOfWork. Una unidad de trabajo es similar a una

    transaccin a nivel de objeto. Una nueva unidad de trabajo se inicia implcitamente cuando inicialmente se crea un

    EntityManager o despus de haber invocado a EntityManager#flush(). Se consigna una unidad de trabajo

    (y se inicia otra nueva) invocando aEntityManager#flush().

    Una unidad de trabajo se puede cerrar manualmente llamando al mtodo EntityManager#close(). Cualquier

    cambio a los objetos dentro de esta unidad de trabajo que an no se haya persistido, se pierde.

    1.8. Trabajando con objetos 49

  • 5/20/2018 Doctrine 2 Orm

    54/239

    Doctrine 2 ORM Documentation, Release 2.1

    Nota: Es muy importante entender que EntityManager#flush()por s mismo, nunca ejecuta las operaciones

    de escritura contra la base de datos. Cualquier otro mtodo como EntityManager#persist($entidad) o

    EntityManager#remove($entidad), nicamente notifica a la Unidad de trabajo que realice estas operaciones

    durante el vaciado.

    El no llamar a EntityManager#flush() conlleva a que se pierdan todos los cambios realizados durante lapeticin.

    1.8.1 Entidades y asignacin de identidad

    Las entidades son objetos con identidad. Su identidad tiene un significado conceptual dentro de tu dominio. En una

    aplicacin CMS (por Content Manager System, en Espaol: Sistema de administracin de contenido) cada artculo

    tiene un identificador nico. Puedes identificar cada artculo por ese id.

    Tomemos el siguiente ejemplo, donde encontramos un artculo titulado Hola Mundo con el id1234:

  • 5/20/2018 Doctrine 2 Orm

    55/239

    Doctrine 2 ORM Documentation, Release 2.1

    private $id;

    /** @Column(type="string") */private $headline;

    /** @ManyToOne(targetEntity="User") */

    private $author;

    /** @OneToMany(targetEntity="Comment", mappedBy="article") */private $comments;

    public function __construct {

    $this->comments = new ArrayCollection();

    }

    public function getAuthor() { return $this->author; }

    public function getComments() { return $this->comments; }

    }

    $article = $em->find(Article, 1);

    Este cdigo slo recupera la instancia del Artculo, conid 1 ejecutando una sola instruccin SELECTen la tabla

    Usuario de la base de datos. Todava puedes tener acceso a las propiedades asociadas Autor y Comentarios y los

    objetos asociados que contienen.

    Esto funciona utilizando el patrn de carga diferida. En lugar de pasar una instancia real del Autor y una coleccin de

    comentarios,Doctrinecrear instancias delegadas para ti. Slo si tienes acceso a estos delegados la primera vez vas a

    ir a travs delEntityManagery cargar su estado desde la base de datos.

    Este proceso de carga diferida, ocurre detrs del escenario, oculto desde tu cdigo. Ve el siguiente fragmento:

  • 5/20/2018 Doctrine 2 Orm

    56/239

    Doctrine 2 ORM Documentation, Release 2.1

  • 5/20/2018 Doctrine 2 Orm

    57/239

    Doctrine 2 ORM Documentation, Release 2.1

    se asignaron con cascade=PERSISTo cascade=ALL(consulta la seccin Persistencia transitiva).

    Si X es una entidad removida, se convierte en gestionada.

    Si X es una entidad independiente, lanzar una excepcin en el vaciado.

    1.8.4 Removiendo entidadesUna entidad se puede remover del almacenamiento persistente pasndola al mtodo

    EntityManager#remove($entidad). Al aplicaa la operacin remove a alguna entidad, esa entidad

    se convierte en REMOVIDA, lo cual significa que su estado persistente se cancelar una vez invocado el

    EntityManager#flush().

    Nota: Al igual que persist, invocar a remove en una entidad no provoca la publicacin inmediata

    de una declaracin DELETE SQL en la base de datos. La entidad se eliminar en la siguiente llamada a

    EntityManager#flush() que implica a esa entidad. Esto significa que las entidades programadas para remo-

    cin an se pueden consultar y aparecen en la consulta y resultados de la coleccin. Ve la seccin en Base de datos y

    unidad de trabajo desincronizadaspara ms informacin.

    Ejemplo:

  • 5/20/2018 Doctrine 2 Orm

    58/239

    Doctrine 2 ORM Documentation, Release 2.1

    2. Usar unDELETE DQLte permite borrar varias entidades de un tipo con una nica orden y sin la hidratacin de

    estas entidades. Esto puede ser muy eficaz para eliminar grandes objetos grficos de la base de datos.

    3. Usar la semntica de clave externas onDelete="CASCADE" puede obligar a la base de datos a eliminar inter-

    namente todos los objetos asociados. Esta estrategia es un poco difcil lograrla bien, pero puede ser muy potente

    y rpida. Debes estar consciente, sin embargo, que al usar la estrategia 1 (CASCADE=REMOVE) evades comple-

    tamente cualquier opcin de clave externa onDelete=CASCADE, porque no obstante,Doctrineexplcitamente

    busca y elimina todas las entidades asociadas.

    1.8.5 Disociando entidades

    Una entidad se disocia de un EntityManager y por lo tanto ya no es gestionada invocando en ella al mtodo

    EntityManager#detach($entidad) o al propagar en cascada las operaciones de disociacin. Los cambios

    realizados a la entidad independiente, en su caso (incluyendo la eliminacin de la entidad), no se sincronizarn con la

    base de datos despus de haber disociado la entidad.

    Doctrineno mantendr ninguna referencia a una entidad disociada.

    Ejemplo:

  • 5/20/2018 Doctrine 2 Orm

    59/239

    Doctrine 2 ORM Documentation, Release 2.1

  • 5/20/2018 Doctrine 2 Orm

    60/239

    Doctrine 2 ORM Documentation, Release 2.1

    base a las referencias mantenidas por el lado propietario de la relacin, como se explica en el captulo Asignando

    asociaciones.

    Cuando invocas a EntityManager#flush(), Doctrine inspecciona todas las entidades gestionadas, nuevas y

    removidas y lleva a cabo las siguientes operaciones.

    Efectos de una base de datos y unidad de trabajo desincronizadas

    Tan pronto como comiences a cambiar el estado de las entidades, llamas a persist o eliminas conteni-

    do de la UnitOfWork, la base de datos estar fuera de sincrona. Slo puedes sincronizarla llamando a

    EntityManager#flush(). Esta seccin describe los efectos producidos cuando la base de datos y la

    UnitOfWorkestn fuera de sincrona.

    Las entidades que se han programado para eliminarse an se pueden consultar desde la base de datos. Estas se

    devuelven desde consultasDQLy del repositorio y son visibles en las colecciones.

    Las entidades pasadas a EntityManager#persistno aparecen en el resultado de la consulta.

    Las entidades que han cambiado no se sobrescribe con el estado de la base de datos. Esto es as porque la

    asignacin de identidad detecta la construccin de una entidad ya existente y asume que esta es la versin

    actualizada.EntityManager#flush()nunca es llamado implcitamente por Doctrine. Siempre tienes que activarlo manual-

    mente.

    Sincronizando entidades nuevas y gestionadas

    La operacin de vaciado se aplica a una entidad gestionada con la semntica siguiente:

    La propia entidad se sincroniza con la base de datos utilizando una declaracin UPDATE SQL, slo si por lo

    menos un campo persistente ha cambiado.

    No hay actualizacionesSQLa ejecutar si la entidad no ha cambiado.

    La operacin de vaciado se aplica a una nueva entidad con la semntica siguiente:La propia entidad se sincroniza con la base de datos usando una instruccin INSERT SQL.

    Para todas las relaciones (iniciadas) de la nueva o gestionada entidad la semntica se aplica a cada entidad X asociada:

    Si X es nueva y las operaciones de persistencia se han configurado en cascada en la relacin, X se conservar.

    Si X es nueva y las operaciones de persistencia no se han configurado en cascada en la relacin, una excepcin

    ser lanzada ya que esto indica un error de programacin.

    Si X es eliminada y las operaciones de persistencia se configuraron en cascada sobre la relacin, una excepcin

    ser lanzada ya que esto indica un error de programacin (X sera persistida de nuevo por la cascada).

    Si X es independiente y las operaciones de persistencia se han configurado en cascada en la relacin, una

    excepcin ser lanzada (esto semnticamente es lo mismo que pasar X a persist()).

    Sincronizando entidades removidas

    La operacin de vaciado se aplica a una entidad removida al eliminar de la base de datos su estado persistente. No hay

    opciones en cascada relevantes para las entidades removidas en el vaciado, las opciones en cascada de remove ya

    estn ejecutadas durante elEntityManager#remove($entidad).

    56 Captulo 1. Gua de referencia

  • 5/20/2018 Doctrine 2 Orm

    61/239

    Doctrine 2 ORM Documentation, Release 2.1

    El tamao de la unidad de trabajo

    El tamao de una unidad de trabajo se refiere principalmente al nmero de entidades administradas en un determinado

    punto en el tiempo.

    El costo del vaciadoQu tan costosa es una operacin de vaciado, depende principalmente de dos factores:

    El tamao de la UnitOfWorkdelEntityManageractual.

    La configuracin de las polticas del control de cambios

    Puedes obtener el tamao de una UnitOfWorkde la siguiente manera:

  • 5/20/2018 Doctrine 2 Orm

    62/239

    Doctrine 2 ORM Documentation, Release 2.1

    case UnitOfWork::STATE_NEW:

    ...

    }

    La entidad se encuentra en estado GESTIONADO si est asociada con un EntityManagery que no se ha REMO-

    VIDO.

    La entidad se encuentra en estado REMOVIDO despus de que se ha pasado a EntityManager#remove() y hastala siguiente operacin de vaciado del mismo EntityManager. Una entidad REMOVIDA todava est asociada con

    unEntityManagerhasta que la siguiente operacin de vaciado.

    La entidad se encuentra en estado DISOCIADO si tiene estado persistente e identidad, pero no est asociada con un

    EntityManager.

    La entidad se encuentra en estado NUEVO si no tiene un estado persistente e identidad y no est asociada con un

    EntityManager(por ejemplo, la acabas de crear a travs del operador new).

    1.8.8 Consultando

    Doctrine2 proporciona los siguientes medios, por nivel de potencia incremental y flexibilidad, para consultar objetos

    persistentes. Siempre debes comenzar con el ms simple que se adapte a tus necesidades.

    Por clave primaria

    La forma de consulta ms bsica para un objeto persistente es su identificador/clave primaria usando el mtodo

    EntityManager#find($nombreEntidad, $id). Aqu est un ejemplo:

  • 5/20/2018 Doctrine 2 Orm

    63/239

    Doctrine 2 ORM Documentation, Release 2.1

    // Todos los usuarios de 20 aos o ms que se apellidan Miller$users = $em->getRepository(MiProyecto\Domain\User)->findBy(array(age => 20, surname

    // Un slo usuario por sobrenombre$user = $em->getRepository(MiProyecto\Domain\User)->findOneBy(array(nickname => romanb

    Tambin puedes cargar asociaciones por el lado propietario a travs del repositorio:

  • 5/20/2018 Doctrine 2 Orm

    64/239

    Doctrine 2 ORM Documentation, Release 2.1

    Una consulta DQLes representada por una instancia de la clase Doctrine\ORM\Query. T creas una consulta

    utilizandoEntityManager#CreateQuery($DQL). He aqu un ejemplo simple:

  • 5/20/2018 Doctrine 2 Orm

    65/239

    Doctrine 2 ORM Documentation, Release 2.1

    Ahora, puedes acceder a tu repositorio llamando a:

  • 5/20/2018 Doctrine 2 Orm

    66/239

    Doctrine 2 ORM Documentation, Release 2.1

    * inverseJoinColumns={@JoinColumn(name="comment_id", referencedColumnName="id")}

    * )

    */private $commentsRead;

    /**

    * Bidireccional - Uno-A-Muchos (Lado inverso)** @OneToMany(targetEntity="Comment", mappedBy="author")

    */private $commentsAuthored;

    /*** Unidireccional - Muchos-A-Uno

    ** @ManyToOne(targetEntity="Comment")

    */private $firstComment;

    }

    /** @Entity */class Comment{

    /** @Id @GeneratedValue @Column(type="string") */private $id;

    /*** Bidireccional - Muchos comentarios son favoritos de muchos usuarios (Lado inverso)

    ** @ManyToMany(targetEntity="User", mappedBy="favorites")

    */private $userFavorites;

    /**

    * Bidireccional - Muchos comentarios fueron redactados por un usuario (Lado propietari** @ManyToOne(targetEntity="User", inversedBy="authoredComments")

    */private $author;

    }

    Estas dos entidades generarn el siguiente esquema MySQL (omitiendo la definicin de claves externas):

    CREATE TABLE User (

    id VARCHAR(255) NOT NULL,

    firstComment_id VARCHAR(255) DEFAULT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    CREATE TABLE Comment (

    id VARCHAR(255) NOT NULL,

    author_id VARCHAR(255) DEFAULT NULL,

    PRIMARY KEY(id)

    ) ENGINE = InnoDB;

    CREATE TABLE user_favorite_comments (

    user_id VARCHAR(255) NOT NULL,

    favorite_comment_id VARCHAR(255) NOT NULL,

    PRIMARY KEY(user_id, favorite_comment_id)

    62 Captulo 1. Gua de referencia

  • 5/20/2018 Doctrine 2 Orm

    67/239

    Doctrine 2 ORM Documentation, Release 2.1

    ) ENGINE = InnoDB;

    CREATE TABLE user_read_comments (

    user_id VARCHAR(255) NOT NULL,

    comment_id VARCHAR(255) NOT NULL,

    PRIMARY KEY(user_id, comment_id)

    ) ENGINE = InnoDB;

    1.9.2 Estableciendo asociaciones

    Crear una asociacin entre dos entidades es directo. Estos son algunos ejemplos de las relaciones unidireccionales del

    Usuario:

  • 5/20/2018 Doctrine 2 Orm

    68/239

    Doctrine 2 ORM Documentation, Release 2.1

    }

    class Comment

    {

    // ...

    public function getUserFavorites() {return $this->userFavorites;

    }

    public function setAuthor(User $author = null) {

    $this->author = $author;

    }