Skip to content

Latest commit

 

History

History
65 lines (53 loc) · 2.09 KB

doctrine-hidden.md

File metadata and controls

65 lines (53 loc) · 2.09 KB

Doctrine's HIDDEN gem

We had a great question from a user recently where the answer involved a little-known Doctrine feature called HIDDEN. You won't need it often, but it deserves its 5 in the spotlight!

HIDDEN allows you to select a field so that you can sort by it... but without include it in the results:

/** @return Voyage[] */
public function findAllOrderedByPastFirst(): array
{
    return $this->createQueryBuilder('voyage')
        ->addSelect('CASE WHEN voyage.leaveAt < :now THEN 1 ELSE 0 END AS HIDDEN isPast')
        ->orderBy('isPast', 'DESC')
        ->setParameter('now', new \DateTimeImmutable())
        ->getQuery()
        ->getResult();
}

The beauty of HIDDEN is that, to orderBy() something, that "something" needs to be selected. But without the HIDDEN, instead of returning an array of Voyage objects, Doctrine would suddenly return an array of arrays, where each array has a 0 key containing the Voyage object and an isPast key. Yikes!

Here are a few other examples shared by users:

Ordering based on State

Ordering based on the "state" of an entity thanks to @ker0x:

$this->createQueryBuilder('voyage')
    ->addSelect(
        'CASE
            WHEN voyage.state = :confirmed THEN 0
            WHEN voyage.state = :canceled THEN 1
            WHEN voyage.state = :accepted THEN 2
            WHEN voyage.state = :pending THEN 3
            ELSE 4
        END AS HIDDEN state_order'
        )
    ->setParameters([
        'confirmed' => Voyage::STATE_CONFIRMED,
        'canceled' => Voyage::STATE_CANCELED,
        'accepted' => Voyage::STATE_ACCEPTED,
        'pending' => Voyage::STATE_PENDING,
    ])
    ->orderBy('state_order', 'ASC');

Ordering Null Values Last

Ordering null values first thanks to @Thibault_1635:

$this->createQueryBuilder('voyage')
    ->addSelect('CASE WHEN voyage.endAt IS NULL THEN 1 ELSE 0 END AS HIDDEN control_null_first')
    ->orderBy('control_null_first', 'DESC');

Have fun!