Reputation: 4528
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
Reputation: 836
use Doctrine\Common\Collections\Criteria;
...
$criteria = Criteria::create();
$criteria->orderBy(['id' => 'DESC']);
return $this->objections->matching($criteria);
Upvotes: 0
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
Reputation: 11859
for ($i = $collection->count(); $i > 0; $i--) {
$orderedCollection->add($collection->get($i));
}
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());
Maybe you should use
Doctrine::getTable('Example')->createQuery('d')
->orderBy('date ASC')
->limit(3);
Upvotes: 20
Reputation: 1
/** @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
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
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
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
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
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