Сортировка Doctrine ArrayCollection по определенному пользовательскому полю

#arrays #symfony #sorting #doctrine #php-7.2

#массивы #symfony #сортировка #doctrine #php-7.2

Вопрос:

Я пытаюсь отсортировать ArrayCollection по определенному полю. ArrayCollection Представляет собой массив курсов. В Course сущности есть вызываемый метод, isLive который возвращает логическое значение.

Я хотел бы отсортировать эту коллекцию, чтобы в начале массива были «живые» курсы, так что это курсы, которые возвращаются true из isLive вызова.

Это код, который у меня есть в настоящее время, но первая запись в $sorted массиве — это не текущий курс.

 $iterator = $this->courses->getIterator();
$iterator->uasort(function ($a, $b) {
   if ($a->isLive() == $b->isLive()) {
      return 0;
   }
   return ($a->isLive() < $b->isLive()) ? -1 : 1;
});
$sorted = new ArrayCollection(iterator_to_array($iterator));
  

Ответ №1:

Это выглядит как хороший вариант использования для критериев Doctrine. Они позволяют фильтровать / сортировать ArrayCollections либо в памяти, если коллекция уже загружена, либо путем добавления предложения WHERE / ORDER BY SQL при следующей загрузке коллекции из базы данных. Итак, это довольно оптимизировано!

Код должен выглядеть примерно так, предполагая, что за live вами стоит isLive() поле:

 $criteria = Criteria::create()
    ->orderBy(["live" => Criteria::DESC])
;

$sorted = $this->courses->matching($criteria);
  

Ответ №2:

Для объекта сделайте это: добавьте аннотацию OrderBy к свойству.

 /**
 * @OneToMany(targetEntity="Course")
 * @OrderBy({"live": "ASC"})
 */
private $courses;
  

Ответ №3:

Я пришел к решению с использованием uasort и array_search , как показано ниже:

 /**
 * @return ArrayCollection
 */
public function getCoursesSortedByLive(): ArrayCollection
{
    $coursesIterator = $this->courses->getIterator();

    $sortOrder = [true];

    $coursesIterator->uasort(function ($a, $b) use ($sortOrder) {
        return array_search($a->isLive(), $sortOrder) - array_search($b->isLive(), $sortOrder);
    });

    return new ArrayCollection(iterator_to_array($sitesIterator));
}