Premise
You suggested 5 correct / worthy solutions, but I think that everything could be reduced to two cases with some minor options.
We know that sorting is always O(NlogN) , so all solutions theoretically have the same performance. But since this is a Doctrine, bottlenecks are the number of SQL queries and hydration methods (i.e., converting data from an array to an instance of an object).
So, you need to choose the "best method", depending on when you need downloadable objects and what you will do with them.
These are my “best solutions” and in general I prefer my solution A)
A) DQL in the bootloader / repository service
Similarly
Nothing out of your business (somehow from 5, see the final note). Alberto Fernandez pointed you in the right direction in the comments.
Best when
DQL is (potentially) the fastest method, because sorting delegates in the DBMS, which is optimized for this. DQL also provides full control over which objects will be retrieved in a single query and hydration mode.
disadvantages
It is not possible (AFAIK) to modify the request created by the Proctrine Proxy classes by configuration, so your application needs to use the repository and call the appropriate method every time you load objects (or override them by default).
Example
class MainEntityRepository extends EntityRepository { public function findSorted(array $conditions) { $qb = $this->createQueryBuilder('e') ->innerJoin('e.association', 'a') ->orderBy('a.value') ;
B) Desired loading and sorting in PHP
Similar to case
Case 2), 3) and 4) is the same as in another place. My version is a general case that applies whenever objects are retrieved. If you need to choose one of them, then I think that solution 3) is the most convenient, since you don’t mess with the entity and is always available, but use the EAGER download (read on).
Best when
If the associated objects are always read, but it is impossible (or convenient) to add a service, then all objects must be loaded by EAGER-ly. Sorting can then be done by PHP, whenever it makes sense for the application: in an event listener, in a controller, in a branch template ... If entities should always be loaded, then the best option is an event listener.
disadvantages
Less flexible than DQL, and sorting in PHP can be a slow operation when the collection is large. In addition, objects should be hydrated as objects that are slow and overflow if the collection is not used for other purposes. Beware of lazy loading, as this will cause one request for each object.
Example
MainEntity.orm.xml:
<?xml version="1.0" encoding="utf-8"?> <doctrine-mapping> <entity name="MainEntity"> <id name="id" type="integer" /> <one-to-many field="collection" target-entity="LinkedEntity" fetch="EAGER" /> <entity-listeners> <entity-listener class="MainEntityListener"/> </entity-listeners> </entity> </doctrine-mapping>
MainEntity.php:
class MainEntityListener { private $id; private $collection; public function __construct() { $this->collection = new ArrayCollection(); }
Concluding observations
- I will not use case 1) as it is, since it is very difficult to introduce inheritance, which reduces encapsulation. Also, I think it has the same complexity and performance of my example.
- Case 5) is not necessarily bad. If the “service” is the application repository, and it uses DQL to sort, then this is my first best case. If this is a custom service to sort the collection only, then I think this is not a good solution.
- All the codes I wrote here are not ready for copy-paste, since my goal was to show my point. Hope this will be a good starting point.
Renouncement
These are “my” best decisions, as I do in my work. Hope will help you and others.