“usort” a Doctrine\Common\Collections\ArrayCollection?

前端 未结 4 1511
隐瞒了意图╮
隐瞒了意图╮ 2020-12-02 16:51

In various cases I need to sort a Doctrine\\Common\\Collections\\ArrayCollection according to a property in the object. Without finding a method doing that righ

相关标签:
4条回答
  • 2020-12-02 17:16

    Since Doctrine 2.3 you can use the Criteria API

    Eg:

    <?php
    
    public function getSortedComments()
    {
        $criteria = Criteria::create()
          ->orderBy(array("created_at" => Criteria::ASC));
    
        return $this->comments->matching($criteria);
    }
    

    Note: this solution requires public access to $createdAt property or a public getter method getCreatedAt().

    0 讨论(0)
  • 2020-12-02 17:20

    To sort an existing Collection you are looking for the ArrayCollection::getIterator() method which returns an ArrayIterator. example:

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

    The easiest way would be letting the query in the repository handle your sorting.

    Imagine you have a SuperEntity with a ManyToMany relationship with Category entities.

    Then for instance creating a repository method like this:

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

    ... makes sorting pretty easy.

    Hope that helps.

    0 讨论(0)
  • 2020-12-02 17:23

    Doctrine criteria does not allow to order by a property on a related object.

    If you want to do it (like me), you have to use the uasort method of the Iterator like a previous response and if you use PHP 7, you can use the Spaceship operator <=> like this :

    /** @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));
    
    0 讨论(0)
  • 2020-12-02 17:29

    If you have an ArrayCollection field you could order with annotations. eg:

    Say an Entity named Society has many Licenses. You could use

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

    That will order the ArrayCollection by endDate (datetime field) in desc order.

    See Doctrine documentation: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/annotations-reference.html#orderby

    0 讨论(0)
提交回复
热议问题