Description
Bug Report
Q | A |
---|---|
Version | 2.1.2 |
Summary
The Criteria::orderBy() method in Doctrine Collections only applies the first ordering pair from the provided array, completely ignoring subsequent orderings. This prevents proper multi-column sorting in Collection filtering.
Current behavior
When using Criteria::orderBy() with multiple sort criteria, only the first key/value pair in the array is applied to the sorting. Any additional orderings are ignored, and changing their direction (ASC/DESC) has no effect on the results.
For example, with two records having the same validFrom date:
When using Criteria::orderBy()
with multiple sort criteria, only the first key/value pair in the array is applied to the sorting. Any additional orderings are ignored, and changing their direction (ASC/DESC) has no effect on the results.
For example, with two records having the same validFrom
date:
// Records:
// id=5, validFrom='2024-12-10 16:04:11'
// id=6, validFrom='2024-12-10 16:04:11'
$collection->matching(
Criteria::create()
->orderBy([
'validFrom' => Criteria::DESC,
'id' => Criteria::DESC // This is ignored
])
);
// Returns id=5 first, despite having same validFrom and lower id
Even changing 'id' => Criteria::ASC
has no effect on the results, demonstrating that the second ordering is completely ignored.
Expected behavior
All orderings in the array should be applied in sequence, matching SQL ORDER BY behavior:
- Primary sorting should be by the first criteria
- When values are equal for the first ordering, subsequent orderings should be used as tiebreakers
- In the example above, id=6 should come first when sorting by validFrom DESC, id DESC
How to reproduce
use Doctrine\Common\Collections\Criteria;
use Doctrine\Common\Collections\ArrayCollection;
class PriceList
{
private int $id;
private \DateTimeImmutable $validFrom;
public function __construct(int $id, \DateTimeImmutable $validFrom)
{
$this->id = $id;
$this->validFrom = $validFrom;
}
public function getId(): int
{
return $this->id;
}
public function getValidFrom(): \DateTimeImmutable
{
return $this->validFrom;
}
}
// Test setup
$list1 = new PriceList(5, new \DateTimeImmutable('2024-12-10 16:04:11'));
$list2 = new PriceList(6, new \DateTimeImmutable('2024-12-10 16:04:11'));
$collection = new ArrayCollection([$list1, $list2]);
$result = $collection->matching(
Criteria::create()
->orderBy([
'validFrom' => Criteria::DESC,
'id' => Criteria::DESC
])
->setMaxResults(1)
);
// Expected: First result has id=6
// Actual: First result has id=5
// Changing to ASC has no effect, proving second ordering is ignored
$result = $collection->matching(
Criteria::create()
->orderBy([
'validFrom' => Criteria::DESC,
'id' => Criteria::ASC
])
->setMaxResults(1)
);
// Still returns id=5 first