I'm trying to order a selection created by Doctrine\Common\Collections\Criteria, http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html#filtering-collections with multiple order attributes as specified possible (?) in the specification of criteria
/**
* @param array $orderings
* @return Criteria
*/
public function orderBy(array $orderings);
however, the collection sorted only takes notice of my first entry in the sorting array. My array of $orderings looks like
array(5) { ["col1"]=> string(3) "ASC" ["col2"]=> string(3) "ASC" ["col3"]=> string(3) "ASC" ["col4"]=> string(3) "ASC" ["col5"]=> string(3) "ASC" }
Any ideas? The docs mentions andX() in the bottom of the page linked earlier but I can't figure out how I would use it in this case.
Cheers, P
I think this is a genuine bug that requires a failing test case.
I have easy fix for this. Could you assign this to me? I need to solve it :)
Whats the ETA on fixing this you'd think @Ocramius ? Need to consider changing strategy or not :)
@pettersoderlund If you can provide a test case it should be easy enough to fix. Ocramius is on holiday till the 24th.
@zeroedin-bill thanks for getting back so quickly!
I did not really figure out where to put a relevant test case but found some changes that might sort it out (pun intended). In the file /doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php
I made the following changes from line 370 according to the comments:
if ($orderings = $criteria->getOrderings()) {
$lnext = null; // history next
foreach (array_reverse($orderings) as $field => $ordering) {
$next = ClosureExpressionVisitor::sortByField($field, $ordering == Criteria::DESC ? -1 : 1, $lnext); // added the history variable
$lnext = $next; // saved history
}
uasort($filtered, $next);
}
Gave a shot at a test case in (that is atm failing) collections/tests/Doctrine/Tests/Common/Collections/ArrayCollectionTest.php
public function testMatchingWithMultipleKeysSortingPreservesyKeys()
{
$object1 = new \stdClass();
$object2 = new \stdClass();
$object1->sortField = 1;
$object2->sortField = 1;
$object1->sortField2 = 1;
$object2->sortField2 = 2;
$collection = new ArrayCollection(array(
'object1' => $object1,
'object2' => $object2,
));
$this->assertSame(
array(
'object1' => $object1,
'object2' => $object2,
),
$collection
->matching(new Criteria(null, array('sortField' => Criteria::ASC, 'sortField2' => Criteria::ASC)))
->toArray()
);
}
This code fixed this bug for me:
foreach (array_reverse($orderings) as $field => $ordering) {
$next = ClosureExpressionVisitor::sortByField($field, $ordering == Criteria::DESC ? -1 : 1, $next );
}
Thank you @joao-gsneto , your code works fine.
I hope this will soon be fixed in the official doctrine release.
This was actually fixed in v1.4.0 by https://github.com/doctrine/collections/commit/4b1e0f4682337c0e0e286de9ab0513eb7d5d284f,
but is it expected that the indexes are not updated?
As a result, calling Collection::offsetGet() or Collection::indexOf() after sorting still returns items/indexes before sorting...
Is there an open issue for that @cdaguerre ? I've just come across this (more than 3 years old) problem...
Most helpful comment
This was actually fixed in v1.4.0 by https://github.com/doctrine/collections/commit/4b1e0f4682337c0e0e286de9ab0513eb7d5d284f,
but is it expected that the indexes are not updated?
As a result, calling
Collection::offsetGet()orCollection::indexOf()after sorting still returns items/indexes before sorting...