Add section on EntityRepository into Getting Started Tutorial.
This commit is contained in:
parent
aab2303c37
commit
e1c2084eeb
@ -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 <http://martinfowler.com/eaaCatalog/repository.html>`_ 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
|
||||
|
||||
<?php
|
||||
$product = $entityManager->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
|
||||
|
||||
<?php
|
||||
$bugs = $entityManager->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
|
||||
|
||||
<?php
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
||||
class BugRepository extends EntityRepository
|
||||
{
|
||||
public function getRecentBugs($number = 30)
|
||||
{
|
||||
$dql = "SELECT b, e, r FROM Bug b JOIN b.engineer e JOIN b.reporter r ORDER BY b.created DESC";
|
||||
|
||||
$query = $entityManager->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
|
||||
|
||||
<?php
|
||||
/**
|
||||
* @Entity @Table(name="bugs", repositoryClass="BugRepository")
|
||||
*/
|
||||
class Bug
|
||||
{
|
||||
//...
|
||||
}
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
|
||||
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
|
||||
|
||||
<entity name="Bug" table="bugs" entity-repository="BugRepository">
|
||||
|
||||
</entity>
|
||||
</doctrine-mapping>
|
||||
|
||||
.. 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
|
||||
|
||||
<?php
|
||||
$bugs = $entityManager->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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user