64

在各种情况下,我需要Doctrine\Common\Collections\ArrayCollection根据对象中的属性对 a 进行排序。在没有找到立即执行此操作的方法的情况下,我这样做:

// $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 数组并返回时,我认为这不是最好的方法。我想知道是否有更好的方法来“取消排序” a Doctrine\Common\Collections\ArrayCollection。我想念任何文档吗?

4

6 回答 6

115

要对现有集合进行排序,您正在寻找返回 ArrayIterator 的ArrayCollection::getIterator()方法。例子:

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

最简单的方法是让存储库中的查询处理您的排序。

想象一下,您有一个 SuperEntity,它与 Category 实体具有多对多关系。

然后例如创建这样的存储库方法:

// 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()
    ;
}

... 使排序变得非常容易。

希望有帮助。

于 2013-05-23T07:08:52.027 回答
61

从 Doctrine 2.3 开始,您可以使用Criteria API

例如:

<?php

public function getSortedComments()
{
    $criteria = Criteria::create()
      ->orderBy(array("created_at" => Criteria::ASC));

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

注意:此解决方案需要公共访问$createdAt属性或公共 getter 方法getCreatedAt()

于 2014-06-16T14:44:57.743 回答
29

如果您有一个 ArrayCollection 字段,您可以使用注释进行排序。例如:

假设一个名为 Society 的实体拥有许多许可证。你可以使用

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

这将按 endDate (日期时间字段)以 desc 顺序对 ArrayCollection 进行排序。

请参阅 Doctrine 文档:http ://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/annotations-reference.html#orderby

于 2015-10-29T22:15:14.600 回答
1

教义标准不允许按相关对象的属性进行排序。

如果你想这样做(像我一样),你必须uasort像以前的响应一样使用 Iterator 的方法,如果你使用 PHP 7,你可以像这样使用 Spaceship 运算符<=>

/** @var \ArrayIterator $iterator */
$iterator = $this->optionValues->getIterator();
$iterator->uasort(function (ProductOptionValue $a, ProductOptionValue $b) {
    return $a->getOption()->getPosition() <=> $b->getOption()->getPosition();
});

return new ArrayCollection(iterator_to_array($iterator));
于 2019-10-29T17:52:16.947 回答
0

在上一个没有 @annotations 的 Symfony 5.3 中,您只需要

...
#[OrderBy(['sortOrder' => 'ASC'])]
private Collection $collection;

#[Column(type: 'integer')]
private int $sortOrder = 0;
...

在您的实体中

于 2021-11-24T12:20:33.517 回答
0

如何获取所有值,对这些值进行排序,然后用排序后的值覆盖属性?

public function sortMyDateProperty(): void
{
    $values = $this->myAwesomeCollection->getValues();
    usort($values, static function (MyAwesomeInterface $a, MyAwesomeInterface $b): int {
        if ($a->getMyDateProperty()->getTimestamp() === $b->getMyDateProperty()->getTimestamp()) {
            return 0;
        }

        return $a->getMyDateProperty() > $b->getMyDateProperty() ? 1 : -1;
    });

    $this->myAwesomeCollection = new ArrayCollection($values);
}
于 2021-12-20T16:06:43.803 回答