按特定的自定义字段对 Doctrine ArrayCollection 进行排序

Sorting a Doctrine ArrayCollection by a specific, custom field

我正在尝试按特定字段对 ArrayCollection 进行排序。 ArrayCollection 是一组课程。在 Course 实体中有一个名为 isLive 的方法,它 return 是一个布尔值。

我想对这个集合进行排序,使 "live" 课程位于数组的开头,因此这是 return 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));

Doctrine Criteria 看起来是个不错的用例。它们允许 filter/sort ArrayCollections,如果集合已经加载,则在内存中,或者通过添加 WHERE / ORDER BY SQL 子句,下次集合将从数据库。所以这是非常优化的!

代码应该看起来像这样,假设你在 isLive() 后面有一个 live 字段:

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

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

我使用 uasortarray_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));
}

对于实体,执行此操作:将 OrderBy 注释添加到 属性。

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