Измените порядок набора доктрин в обратном порядке
Я ищу чистый способ изменить порядок коллекции доктрины. Я знаю, это звучит странно, поэтому позвольте мне объяснить мою (простую) цель: мне нужно отобразить x последнюю/новейшую запись , но я должен отобразить ее в обратном порядке: самая старая 1-я и т. Д.
Если это неясно, вот пример : Допустим, у меня есть это в моей таблице (назовем это "примером"):
id date
1 2012-01-21
2 2012-03-19
3 2012-02-21
4 2012-03-21
До сих пор я делал это:
Doctrine::getTable('Example')->createQuery('d')
->orderBy('date DESC')
->limit(3);
, который возвращает это
id date
4 2012-03-21
2 2012-03-19
3 2012-02-21
Но Я хочу этого:
id date
3 2012-02-21
2 2012-03-19
4 2012-03-21
Изменить:
Я нашел решение этой проблемы, используя промежуточный массив и используя для него array_reverse. Но это выглядит не очень хорошо:(
Вот код, который я написал:
$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
Правка 2: ответ от @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));
}
7 answers
Без промежуточного массива:
for($i=$collection->count(); $i>0; $i--){
$orderedCollection->add($collection->get($i);
}
Надеюсь, хороший ответ:
Вы можете экспортировать коллекцию в массив и отменить ее
$query = Doctrine::getTable('Example')
->createQuery('e')
->orderBy('date DESC')
->limit(3)
$collection = $query->execute();
$collection = array_reverse($collection->toArray());
Старый (неправильный) ответ:
Может быть, вам следует использовать
Doctrine::getTable('Example')->createQuery('d')
->orderBy('date ASC')
->limit(3);
Похоже, что вам либо нужно настроить Doctrine_collection, чтобы предоставить что-то похожее на array_reverse
в вашем классе коллекций, либо использовать какой-то хакерский подход, подобный следующему:
$keys = array_reverse($collection->getKeys());
foreach ($keys as $key) {
$object = $collection->get($key);
}
Если вы не хотите использовать какие-либо специальные функции сбора, просто повторите элементы в обратном порядке (без каких-либо накладных расходов), вы можете сделать это довольно легко, вот так:
/** @var $results Doctrine_Collection this is your result collection */
$iterator = $results->getIterator();
$item = end($iterator);
do {
var_dump($item);
} while ($item = prev($iterator));
Может быть, вам следует использовать вот так
->orderBy('date', 'DESC')
Потому что в этой документации http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/query-builder.html{[7] } подпись orderby требует ASC/DESC в качестве второго параметра
public function orderBy($sort = null, $order = null);
Если вам нужен объект ArrayCollection
, другое решение этой проблемы, которое расширяет ответ, данный @adam-kiss, состоит в том, чтобы использовать возвращаемое значение array_reverse
для создания нового объекта ArrayCollection
, который уменьшает необходимость цикла for
.
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()));
Судя по всему, конечно, просто удалите "DESC" из заказа. Запрос возвращает дату в порядке убывания точно так, как указано, и вы хотите, чтобы она была в порядке возрастания.
Для доктрины\ИЛИ\постоянной коллекции
/** @var Doctrine\ORM\PersistentCollection $posts */
$posts = $category->getPosts();
for ($i = $posts->count()-1; $i >= 0; $i--) {
$post = $posts->offsetGet($i);
// ... do some logic
}