El Administrador de entidades es el punto de acceso primario a la característica de ORM que provee Doctrine.
El
EntityManager
es una clase de Doctrine que se encuentra en el namespaceDoctrine\ORM
y se usa para recuperar entidades de nuestros repositorios usando un criterio de búsqueda y, además, guarda entidades en la base de datos.
El EntityManager
se registra como un servicio en el administrador de servicios
de Zend Framework 3. Desde nuestra clase factory recuperamos el EntityManager
del
administrador de servicios de la siguiente manera (si necesitamos una conexión
diferente a la orm_default
, solamente reemplazamos orm_default
con el nombre
de la conexión a la base de datos adecuada):
// Get Doctrine entity manager
$entityManager = $container->get('doctrine.entitymanager.orm_default');
Los métodos más usados provistos por la clase EntityManager
se listan en la tabla
12.4 que se muestra abajo:
Método | Descripción |
---|---|
persist($entity) |
Coloca una nueva entidad dentro del administrador de entidades (se hace manejable). |
remove($entity) |
Remueve una entidad de la base de datos. |
flush() |
Purga todos los cambios del objeto que están en cola hasta ahora hacia la base de datos. |
createQuery($dql) |
Crea un nuevo objeto Query. |
getRepository($entityName) |
Traer un repositorio para una clase de tipo entidad. |
Vamos a revisar los métodos de la tabla 12.4.
Para agregar una entidad creada recientemente al administrador de entidades (haciendo
a la entidad "administrada") usamos el método persist()
. Para remover una entidad
de la base de datos usamos el método remove()
del administrador de eventos.
Cuando llamamos a persist()
o remove()
el EntityManager
recuerda nuestros
cambios en memoria pero no aplica los cambios en la base de datos automáticamente
(por razones de rendimiento). Para aplicar los cambios en la base de datos, en una
única transacción, usamos el método flush()
.
Por ejemplo, el código de ejemplo de abajo muestra como crear una instancia de la
entidad Post
y como guardarla en la base de datos:
// Create new Post entity.
$post = new Post();
$post->setTitle('Top 10+ Books about Zend Framework 3');
$post->setContent('Post body goes here');
$post->setStatus(Post::STATUS_PUBLISHED);
$currentDate = date('Y-m-d H:i:s');
$post->setDateCreated($currentDate);
// Add the entity to entity manager.
$entityManager->persist($post);
// Apply changes to database.
$entityManager->flush();
El método createQuery()
del administrador de entidades esta diseñado para crear
una consulta desde un cadena de caracteres DQL. Este regresa un objeto Query
.
Luego, se ejecuta la consulta y regresa los resultados (un arreglo de entidades
que concuerda con las condiciones de búsqueda).
El método getRepository()
del administrador de entidades esta diseñado para traer
el repositorio a partir del nombre de la clase de tipo entidad. Podemos ver abajo,
por ejemplo, como se trae el repositorio para la entidad Post
:
$repository = $entityManager->getRepository(Post::class);
Conceptualmente cada clase de tipo entidad tiene su propio repositorio. El repositorio
provee métodos para recuperar entidades de la base de datos. El repositorio puede
ser considerado como la colección de todas las entidades disponibles de determinada
clase. Por ejemplo, existen repositorios para las entidades Post
, Comment
y
Tag
.
Para cargar datos desde la base de datos recuperamos una entidad de su repositorio. Cuando pedimos el repositorio para una entidad se cargan los datos desde la tabla asociada a la entidad y se asignan los campos de la entidad a los datos.
La clase
Doctrine\ORM\EntityRepository
implementa el repositorio por defecto. Si lo necesitamos, podemos crear nuestro propio repositorio extendiendo la claseEntityRepository
. Mostraremos esto más adelante.
Los métodos más usado que provee la clase EntityRepository
se listan en la tabla
12.5:
Métodos | Descripción |
---|---|
findAll() |
Busca todas las entidades en el repositorio. |
find($id) |
Busca a una entidad a partir de su identificador. |
findBy($criteria, $orderBy, $limit, $offset) |
Busca una entidad a partir de un conjunto de criterios. |
findOneBy($criteria, $orderBy) |
Busca una sola entidad a partir de un conjunto de criterios. |
createQueryBuilder($alias) |
Crea una nueva instancia del QueryBuilder que es prepoblada con la entidad. |
El método findAll()
trae todas las entidades desde el repositorio. Un ejemplo
simple sobre como usarla se muestra abajo:
// Find all posts from repository
$posts = $entityManager->getRepository(Post::class)->findAll();
El método find()
es el método más simple para buscar una entidad. Este recupera
una entidad a partir de su ID (llave primaria).
En el ejemplo de abajo seleccionamos la publicación con ID = 1.
// Find post by primary key (ID)
$post = $entityManager->getRepository(Post::class)->find(1);
El método findBy()
toma un argumento como criterio de búsqueda (y opcionalmente
uno de ordenamiento y un límite) y regresa una colección de entidades que coinciden
con el criterio. El método findOneBy()
es muy similar al método findBy()
,
pero este solo regresa la primera entidad que se ajusta al criterio de búsqueda.
En el código de abajo usamos el método findBy()
para seleccionar las 50 publicaciones
publicadas más recientes:
// Find 50 most recent published posts
$posts = $entityManager->getRepository(Post::class)->findBy(
['status'=>Post::STATUS_PUBLISHED],
['dateCreated'=>'DESC'], 50);
Para nuestra conveniencia la clase EntityRepository
provee además métodos mágicos
que nos permiten consultar entidades mediante el nombre del atributo, es decir,
con los métodos findByX
y FindOneByX
(donde X debe reemplazarse con el nombre
del atributo):
// Query a single post by ID attribute
$post = $entityManager->getRepository(Post::class)->findOneById(1);
// Query posts by status attribute
$posts = $entityManager->getRepository(Post::class)
->findByStatus(Post::STATUS_PUBLISHED);
Y el método de búsqueda más complejo es createQueryBuilder()
. Este método permite
crear consultas DQL complejas.
Si los métodos estándar no son suficientes (o si tenemos criterios de búsqueda complejos
y consultas DQL) podemos crear nuestro propio repositorio extendiendo la clase
estándar EntityRepository
y encapsular la lógica de la búsqueda allí. Mostraremos
como hacer esto luego cuando implementemos la característica tag cloud para nuestro
Blog de ejemplo.