"usort"一个Doctrine\Common\Collections\ArrayCollection?

lui*_*s90 49 php doctrine-orm

在各种情况下,我需要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);
}
Run Code Online (Sandbox Code Playgroud)

我认为这不是最好的方法,你必须将所有内容复制到本机PHP数组并返回.我想知道是否有更好的方式来"使用"a Doctrine\Common\Collections\ArrayCollection.我想念任何文件吗?

Nic*_*ich 94

要对现有Collection进行排序,您要查找返回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));
Run Code Online (Sandbox Code Playgroud)

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

想象一下,你有一个与类别实体具有ManyToMany关系的SuperEntity.

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

// 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()
    ;
}
Run Code Online (Sandbox Code Playgroud)

......使排序变得非常简单.

希望有所帮助.

  • 对于其他发现此问题的人,您也可以使用 $a = $collection-&gt;toArray(); 将 ArrayCollection 转换为数组。然后是 $collection = new ArrayCollection($a); (4认同)

iol*_*leo 49

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

例如:

<?php

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

    return $this->comments->matching($criteria);
}
Run Code Online (Sandbox Code Playgroud)

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

  • 实际上,您可以对集合对象本身执行基本匹配和排序标准.来自docs:"Criteria有一个有限的匹配语言,可以在SQL和PHP集合级别上运行." 超级方便! (2认同)

akr*_*krz 22

如果您有一个ArrayCollection字段,则可以使用注释进行订购.例如:

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

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

这将按照desc顺序通过endDate(datetime字段)对ArrayCollection进行排序.

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

  • 请注意,它不适用于EAGER提取模式.https://github.com/doctrine/doctrine2/issues/4256 (3认同)