haltabush
haltabush

Reputation: 4528

Reverse the order of a Doctrine_Collection

I'm looking for a clean way to reverse the order of a Doctrine_Collection. I know it sounds weird, so let me explain my (simple) goal: I need to display the x latest/newest record, but I have to display it in the reverse order: the oldest 1st, etc.

If it's unclear, here is an example : Lets say I have this in my table (lets call it 'example') :

id      date
1       2012-01-21
2       2012-03-19
3       2012-02-21
4       2012-03-21

So far, I've done this:

Doctrine::getTable('Example')->createQuery('d')
    ->orderBy('date DESC')
    ->limit(3);

Which returns that

id      date
4       2012-03-21
2       2012-03-19
3       2012-02-21

But I want that:

id      date
3       2012-02-21
2       2012-03-19
4       2012-03-21

Edit:

I've found a solution to this, using intermediate array & using array_reverse on it. But it doesn't look good :(

Here is the code I've written:

    $query = Doctrine::getTable('Example')
            ->createQuery('e')
            ->orderBy('date DESC')
            ->limit(3)
        $collection = $query->execute();

        //Here is the dirty hack:
        $itemArray = array();
        foreach ($collection as $item) {
            $itemArray[] = $item;
        }
        $itemArray = array_reverse($itemArray);
        $orderedCollection = new Doctrine_Collection($doctrineClass);
        foreach($itemArray as $item) {
            $orderedCollection->add($item);
        }
        //OrderedCollection is OK but... come on! There must be a cleaner way to do it

Edit 2 : answer from @Adam Kiss

        $query = Doctrine::getTable('Example')
            ->createQuery('e')
            ->orderBy('date DESC')
            ->limit(3)
        $collection = $query->execute();

        //Here is the **lovely** hack:
        $orderedCollection = new Doctrine_Collection('Example');
        for ($i=($collection->count() - 1); $i>=0;$i--) {
            $orderedCollection->add($collection->get($i));
        }

Upvotes: 14

Views: 21169

Answers (9)

Cesur APAYDIN
Cesur APAYDIN

Reputation: 836

use Doctrine\Common\Collections\Criteria;
...

$criteria = Criteria::create();
$criteria->orderBy(['id' => 'DESC']);

return $this->objections->matching($criteria);

Upvotes: 0

yuta.kuroda
yuta.kuroda

Reputation: 1

it worked for me. doctrine version: 1.2

    $collection = //make doctrine collection;
    $reversed_array = array_reverse($collection->toArray());
    $collection->fromArray($reversed_array);

Upvotes: 0

Adam Kiss
Adam Kiss

Reputation: 11859

Without intermediate array:

for ($i = $collection->count(); $i > 0; $i--) {
    $orderedCollection->add($collection->get($i));
}

Hopefully good answer:

You could export Collection to array and reverse it

$query = Doctrine::getTable('Example')
         ->createQuery('e')
         ->orderBy('date DESC')
         ->limit(3)
$collection = $query->execute();
$collection = array_reverse($collection->toArray());

Old (wrong) answer:

Maybe you should use

Doctrine::getTable('Example')->createQuery('d')
  ->orderBy('date ASC')
  ->limit(3);

Upvotes: 20

Martin Belobrad
Martin Belobrad

Reputation: 1

For Doctrine\ORM\PersistentCollection

/** @var Doctrine\ORM\PersistentCollection $posts */
$posts = $category->getPosts();
for ($i = $posts->count()-1; $i >= 0; $i--) {
    $post = $posts->offsetGet($i);
    // ... do some logic
}

Upvotes: 0

Chris
Chris

Reputation: 455

By the looks of it, surely just remove "DESC" from the orderby. The query returns in date descending order exactly as it's told and you want it in ascending order.

Upvotes: 1

ghindle
ghindle

Reputation: 560

If you want an ArrayCollection object, another solution to this which expands on the answer given by @adam-kiss is to use the returned value of array_reverse to construct a new ArrayCollection object which reduces the need of a for loop.

use Doctrine\Common\Collections\ArrayCollection;

$query = Doctrine::getTable('Example')
    ->createQuery('e')
    ->orderBy('date DESC')
    ->limit(3)
;
$collection = $query->execute();
$orderedCollection = new ArrayCollection(array_reverse($collection->toArray()));

Upvotes: 0

Ekrem
Ekrem

Reputation: 483

maybe you should use like this

     ->orderBy('date', 'DESC')

because in this documentation http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/query-builder.html orderby's signature requires ASC/DESC as second parameter

      public function orderBy($sort = null, $order = null);

Upvotes: 0

1ed
1ed

Reputation: 3668

If you don't want to use any special collection functionality, just iterate over of the elements in reverse order (without any overhead) you can do it pretty easy like this:

/** @var $results Doctrine_Collection this is your result collection */
$iterator = $results->getIterator();
$item = end($iterator);

do {
  var_dump($item);
} while ($item = prev($iterator));

Upvotes: 8

dbrumann
dbrumann

Reputation: 17166

It seems like you either have to customize Doctrine_collection to provide something similar to array_reverse within your collection-class or use some hackish approach like the following:

$keys = array_reverse($collection->getKeys());
foreach ($keys as $key) {
    $object = $collection->get($key);
}

Upvotes: 7

Related Questions