«Усортировать» Учение \ Общее \ Коллекции \ ArrayCollection?

В разных случаях мне нужно сортироватьDoctrine\Common\Collections\ArrayCollection согласно собственности в объекте. Не найдя метод, который делает это сразу, я делаю это:

// $collection instanceof Doctrine\Common\Collections\ArrayCollection
$array = $collection->getValues();
usort($array, function($a, $b){
    return ($a->getProperty() < $b->getProperty()) ? -1 : 1 ;
});

$collection->clear();
foreach ($array as $item) {
    $collection->add($item);
}

Я предполагаю, что это не лучший способ, когда вам нужно копировать все в собственный массив PHP и обратно. Интересно, есть ли лучший способУсорт "аDoctrine\Common\Collections\ArrayCollection, Я скучаю по любому документу?

Ответы на вопрос(3)

Если у вас есть поле ArrayCollection, вы можете заказать с аннотациями. например:

Скажем, организация под названием Общество имеет много лицензий. Вы могли бы использовать

/**
* @ORM\OneToMany(targetEntity="License", mappedBy="society")
* @ORM\OrderBy({"endDate" = "DESC"})
**/
private $licenses;

Это упорядочит ArrayCollection по endDate (поле datetime) в порядке убывания.

Смотрите документацию Doctrine:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/annotations-reference.html#orderby

 Aistis20 окт. 2016 г., 13:49
Имейте ввиду, что он не будет работать в режиме извлечения EAGER.github.com/doctrine/doctrine2/issues/4256
Решение Вопроса

Для сортировки существующей коллекции вы ищетеArrayCollection :: getIterator () метод, который возвращает ArrayIterator. пример:

$iterator = $collection->getIterator();
$iterator->uasort(function ($a, $b) {
    return ($a->getPropery() < $b->getProperty()) ? -1 : 1;
});
$collection = new ArrayCollection(iterator_to_array($iterator));

Самым простым способом было бы позволить запросу вхранилище справиться с вашей сортировкой.

Представьте, что у вас есть SuperEntity с отношениями ManyToMany с категориями.

Затем, например, создайте метод репозитория, подобный этому:

// Vendor/YourBundle/Entity/SuperEntityRepository.php

public function findByCategoryAndOrderByName($category)
{
    return $this->createQueryBuilder('e')
        ->where('e.category = :category')
        ->setParameter('category', $category)
        ->orderBy('e.name', 'ASC')
        ->getQuery()
        ->getResult()
    ;
}

... делает сортировку довольно простой

Надеюсь, это поможет.

 nifr15 авг. 2013 г., 16:54
usort hasn 't был реализован для ArrayIterator ... так что в настоящее время это невозможно. googlin' вы найдете несколько запросов к функциям и несколько вопросов о стекопереработке, касающихся этой проблемы. надеюсь, это поможет
 Reza S26 окт. 2013 г., 03:23
Спасибо Спасибо! ты спас меня в пятницу вечером!
 Ryan30 авг. 2016 г., 02:00
Тот'это правда. Хотя пример, который дает ОП, выглядит для этого хорошим кандидатом. Реализация критериев доктрины намеренно очень минимальна.
 Sam16 дек. 2014 г., 17:47
@AlainTiemblo спасибо!
 luiges9023 мая 2013 г., 11:03
Итератор сортирует, но неКажется, я пишу в коллекцию ... Я что-то пропустил?
 Faery15 авг. 2013 г., 11:08
Можноuasort заменен наusort? Я попробовал это, но я получил Erorr -Call to undefined method ArrayIterator::usort()
 calumbrodie25 апр. 2014 г., 13:00
Для любого, кто найдет это, вы также можете просто преобразовать ArrayCollection в массив, используя $ a = $ collection->ToArray (); затем следует $ collection = new ArrayCollection ($ a);
 ctatro8507 мая 2018 г., 16:10
Это стоит отметить: если вы используете uasort, и ваша коллекция имеет цифровые ключи, убедитесь, что вы установили второй параметр iterator_to_array как false, а затем присвоили его обратно в коллекцию, в противном случае массив может вернуться к предыдущая сортировка, это особенно верно, если вы возвращаете результаты в ответе json.
 galeaspablo27 авг. 2016 г., 18:03
@ Райан, но ты можешьне используйте критерии, если высортировать по чему-то, чтоне собственность. Представьте себе сущность вArrayCollection имеет свойствоtags этоArrayCollection и вы хотите отсортировать по количеству тегов. Я неДумаю, критерии помогут.
 Ryan28 апр. 2016 г., 01:41
Ответstackoverflow.com/a/24246304/563394 ниже теперь гораздо лучший вариант.
 Sam14 авг. 2014 г., 12:06
@nifr Как бы вы тогда использовали этот новый метод репо в вашей сущности? Например. если я хочуSuperEntitygetCategory метод возврата упорядоченных результатов.
 Alain Tiemblo14 дек. 2014 г., 13:29
@ Сэм, я только что понял твою проблему ... и наконец нашел обходной путь. Для тех, кто заинтересован, вы можете посмотреть на мой вопрос / ответВот.
 nifr23 мая 2013 г., 11:42
обновил мой ответ! кажется, я знаю, что вы хотели - добавил iterator_to_array ... приемлемо сейчас? :)

Начиная с Doctrine 2.3 вы можете использоватьКритерии API

Например:

orderBy(array("created_at" => Criteria::ASC));

    return $this->comments->matching($criteria);
}

Примечание: это решение требует публичного доступа к$createdAt собственность или публичный метод получения.getCreatedAt()

 ioleo12 сент. 2016 г., 20:58
downvoters: пожалуйста, объясните, почему вы проголосовали? если этот ответ может быть улучшен, пожалуйста, поделитесь
 Logan Bailey21 окт. 2014 г., 23:06
Это будет работать только с доктринойс ORM, ODM 'Постоянная коллекция не поддерживает сопоставление.
 dubrox05 февр. 2015 г., 17:33
Безразлично»Кажется, что это работает, если свойство (то есть, made_at) не является публичным :(
 thinice12 дек. 2014 г., 21:49
На самом деле вы можете выполнить базовые критерии соответствия и сортировки для самих объектов коллекции. Из документов: "Критерии имеют ограниченный язык соответствия, который работает как на SQL, так и на уровне коллекции PHP »., Супер удобно!
 Ryan28 апр. 2016 г., 01:40
Это намного лучшее решение сейчас.
 Clutch04 апр. 2016 г., 22:29
Я прочитал или протестировал его и считаю, что для получения информации ему нужна открытая переменная или метод с именем getCreated_At () или что-то в этом роде. Это отстой, потому что я неОбычно я получаю методы получения.
 Yep_It's_Me21 мар. 2018 г., 08:52
Мне пришлось позвонитьarray_values на возвращаемое значениеmatching()потому что он используетuasort который сохраняет индексы.
 ioleo20 апр. 2016 г., 11:49
@dubrox, как говорит @Clutch, вам нужен публичный метод полученияgetCreatedAt

Ваш ответ на вопрос