Ordering To-Many Associations
-----------------------------

There are use-cases when you'll want to sort collections when they are
retrieved from the database. In userland you do this as long as you
haven't initially saved an entity with its associations into the
database. To retrieve a sorted collection from the database you can
use the ``#[OrderBy]`` attribute with a collection that specifies
a DQL snippet that is appended to all queries with this
collection.

Additional to any ``#[OneToMany]`` or ``#[ManyToMany]`` attribute you
can specify the ``#[OrderBy]`` in the following way:

.. configuration-block::

    .. code-block:: attribute

        <?php

        use SortDirection;

        #[Entity]
        class User
        {
            // ...

            #[ManyToMany(targetEntity: Group::class)]
            #[OrderBy([
                'name' => SortDirection::Ascending,
                'createdAt' => SortDirection::Descending,
            ])]
            private Collection $groups;
        }

    .. code-block:: xml

        <doctrine-mapping>
            <entity name="User">
                <many-to-many field="groups" target-entity="Group">
                    <order-by>
                        <order-by-field name="name" direction="ASC" />
                        <order-by-field name="createdAt" direction="DESC" />
                    </order-by>
                </many-to-many>
            </entity>
        </doctrine-mapping>

The DQL Snippet representing the field is only allowed to consist of
unqualified, unquoted field names. The direction can be either ``ASC``
or ``DESC`` and is mandatory when using attributes, but optional when
using XML.
When using the XML driver, the direction defaults to ``ASC`` if not specified.

The referenced field names have to exist on the ``targetEntity`` class
of the ``#[ManyToMany]`` or ``#[OneToMany]`` attribute.

The semantics of this feature can be described as follows:


-  ``@OrderBy`` acts as an implicit ORDER BY clause for the given
   fields, that is appended to all the explicitly given ORDER BY
   items.
-  All collections of the ordered type are always retrieved in an
   ordered fashion.
-  To keep the database impact low, these implicit ORDER BY items
   are only added to a DQL Query if the collection is fetch joined in
   the DQL query.

Given our previously defined example, the following would not add
ORDER BY, since g is not fetch joined:

.. code-block:: sql

    SELECT u FROM User u JOIN u.groups g WHERE SIZE(g) > 10

However the following:

.. code-block:: sql

    SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10

...would internally be rewritten to:

.. code-block:: sql

    SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 ORDER BY g.name ASC

You can reverse the order with an explicit DQL ORDER BY:

.. code-block:: sql

    SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 ORDER BY g.name DESC

...is internally rewritten to:

.. code-block:: sql

    SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 ORDER BY g.name DESC, g.name ASC
