Orm: Doctrine 2 Criteria using multiple orderings

Created on 9 Dec 2015  路  10Comments  路  Source: doctrine/orm

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

Bug

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() or Collection::indexOf() after sorting still returns items/indexes before sorting...

All 10 comments

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...

Was this page helpful?
0 / 5 - 0 ratings