1
0
mirror of synced 2025-03-21 23:43:53 +03:00

Add section on EntityRepository into Getting Started Tutorial.

This commit is contained in:
Benjamin Eberlei 2011-02-26 11:51:30 +01:00
parent aab2303c37
commit e1c2084eeb

View File

@ -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 changed columns are updated, which offers a pretty good performance
improvement compared to updating all the properties. 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 This tutorial is over here, I hope you had fun. Additional content
will be added to this tutorial incrementally, topics will include: will be added to this tutorial incrementally, topics will include:
* Entity Repositories - More on Association Mappings
* More on Association Mappings - Lifecycle Events triggered in the UnitOfWork
* Lifecycle Events triggered in the UnitOfWork - Ordering of Collections
* Ordering of Collections
Additional details on all the topics discussed here can be found in Additional details on all the topics discussed here can be found in
the respective manual chapters. the respective manual chapters.