From e1c2084eeb6aab347cac93dceec8071b9cc293a6 Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Sat, 26 Feb 2011 11:51:30 +0100 Subject: [PATCH] Add section on EntityRepository into Getting Started Tutorial. --- en/tutorials/getting-started-xml-edition.rst | 149 ++++++++++++++++++- 1 file changed, 145 insertions(+), 4 deletions(-) diff --git a/en/tutorials/getting-started-xml-edition.rst b/en/tutorials/getting-started-xml-edition.rst index 093386159..a8b435b8c 100644 --- a/en/tutorials/getting-started-xml-edition.rst +++ b/en/tutorials/getting-started-xml-edition.rst @@ -1151,13 +1151,154 @@ entity is scheduled for an UPDATE against the database. Only the changed columns are updated, which offers a pretty good performance improvement compared to updating all the properties. +Entity Repositories +------------------- + +For now we have not discussed how to separate the Doctrine query logic from your model. +In Doctrine 1 there was the concept of ``Doctrine_Table`` instances for this +seperation. The similar concept in Doctrine2 is called Entity Repositories, integrating +the `repository pattern `_ at the heart of Doctrine. + +Every Entity uses a default repository by default and offers a bunch of convenience +methods that you can use to query for instances of that Entity. Take for example +our Product entity. If we wanted to Query by name, we can use: + +.. code-block:: php + + getRepository('Product') + ->findOneBy(array('name' => $productName)); + +The method ``findOneBy()`` takes an array of fields or association keys and the values to match against. + +If you want to find all entities matching a condition you can use ``findBy()``, for +example querying for all closed bugs: + +.. code-block:: php + + getRepository('Bug') + ->findBy(array('status' => 'CLOSED')); + + foreach ($bugs AS $bug) { + // do stuff + } + +Compared to DQL these query methods are falling short of functionality very fast. +Doctrine offers you a convenient way to extend the functionalities of the default ``EntityRepository`` +and put all the specialized DQL query logic on it. For this you have to create a subclass +of ``Doctrine\ORM\EntityRepository``, in our case a ``BugRepository`` and group all +the previoiusly discussed query functionality in it: + +.. code-block:: php + + createQuery($dql); + $query->setMaxResults($number); + return $query->getResult(); + } + + public function getRecentBugsArray($number = 30) + { + $dql = "SELECT b, e, r, p FROM Bug b JOIN b.engineer e ". + "JOIN b.reporter r JOIN b.products p ORDER BY b.created DESC"; + $query = $em->createQuery($dql); + $query->setMaxResults($number); + return $query->getArrayResult(); + } + + public function getUsersBugs($userId, $number = 15) + { + $dql = "SELECT b, e, r FROM Bug b JOIN b.engineer e JOIN b.reporter r ". + "WHERE b.status = 'OPEN' AND e.id = ?1 OR r.id = ?1 ORDER BY b.created DESC"; + + return $entityManager->createQuery($dql) + ->setParameter(1, $userId) + ->setMaxResults($number) + ->getResult(); + } + + public function getOpenBugsByProduct() + { + $dql = "SELECT p.id, p.name, count(b.id) AS openBugs FROM Bug b ". + "JOIN b.products p WHERE b.status = 'OPEN' GROUP BY p.id"; + return $em->createQuery($dql)->getScalarResult(); + } + } + +To be able to use this query logic through ``$entityManager->getRepository('Bug')`` +we have to adjust the metadata slightly. + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + .. code-block:: yaml + + Product: + type: entity + repositoryClass: BugRepository + +Now we can remove our query logic in all the places and instead use them through the EntityRepository. +As an example here is the code of the first use case "List of Bugs": + +.. code-block:: php + + getRepository('Bug')->getRecentBugs(); + + foreach($bugs AS $bug) { + echo $bug->description." - ".$bug->created->format('d.m.Y')."\n"; + echo " Reported by: ".$bug->getReporter()->name."\n"; + echo " Assigned to: ".$bug->getEngineer()->name."\n"; + foreach($bug->getProducts() AS $product) { + echo " Platform: ".$product->name."\n"; + } + echo "\n"; + } + +Using EntityRepositories you can avoid coupling your model with specific query logic. +You can also re-use query logic easily throughout your application. + +Conclusion +---------- + This tutorial is over here, I hope you had fun. Additional content will be added to this tutorial incrementally, topics will include: -* Entity Repositories -* More on Association Mappings -* Lifecycle Events triggered in the UnitOfWork -* Ordering of Collections +- More on Association Mappings +- Lifecycle Events triggered in the UnitOfWork +- Ordering of Collections Additional details on all the topics discussed here can be found in the respective manual chapters.