2013-05-23 11 views
31

In verschiedenen Fällen muss ich eine Doctrine\Common\Collections\ArrayCollection nach einer Eigenschaft im Objekt sortieren. Ohne ein Verfahren zu finden, das sofort zu tun, das tue ich dies:"Usort" eine 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); 
} 

Ich nehme dies nicht der beste Weg ist, wenn man alles auf native PHP-Array kopieren und zurück. Ich frage mich, ob es eine bessere Möglichkeit gibt, ein Doctrine\Common\Collections\ArrayCollection "usort". Vermisse ich ein Dokument?

Antwort

70

Um eine vorhandene Sammlung zu sortieren, suchen Sie nach der ArrayCollection :: getIterator() Methode, die einen ArrayIterator zurückgibt. Beispiel:

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

Der einfachste Weg, um die Abfrage in den Ihre Sortier behandelt Repository lassen würde.

Stellen Sie sich vor, Sie haben eine SuperEntity mit einer ManyToMany-Beziehung zu Kategorieentitäten.

Dann zum Beispiel einer Repository Methode wie folgt zu erstellen:

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

... macht das Sortieren recht einfach.

Hoffe, dass hilft.

+0

Iterator Art ist, aber scheint nicht zu der Sammlung zu schreiben durch ... Habe ich etwas verpasst? – luiges90

+0

aktualisiert meine Antwort! Ich denke, ich weiß, was Sie wollten - hinzugefügt iterator_to_array ... jetzt akzeptabel? :) – nifr

+0

Kann 'uasort' durch ersetzt werden mit' usort'? Ich habe es versucht, aber ich erorr-Call zu undefinierte Methode ArrayIterator :: usort() ' – Faery

34

Seit 2.3 Lehre können Sie die Criteria API

ZB verwenden:

<?php 

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

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

Hinweis: Diese Lösung erfordert den Zugang der Öffentlichkeit zu $createdAt Eigenschaft oder einem öffentlichen Getter-Methode getCreatedAt().

+0

Dies funktioniert nur mit ORM von Doctrine, die persistente Sammlung des ODM unterstützt kein Matching. –

+2

Tatsächlich können Sie grundlegende Kriterien für die Zuordnung und Sortierung der Sammlungsobjekte selbst vornehmen. Aus der Dokumentation: "Die Kriterien haben eine begrenzte übereinstimmende Sprache, die sowohl auf der SQL- als auch auf der PHP-Sammlungsebene funktioniert." Super praktisch! – thinice

+0

Scheint nicht zu funktionieren, wenn die Eigenschaft (dh created_at) nicht öffentlich ist :( – dubrox

10

Wenn Sie ein ArrayCollection-Feld haben, können Sie mit Anmerkungen bestellen. zB:

Sagen Sie eine Entität namens Society hat viele Lizenzen. Sie könnten

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

verwenden. Das wird die ArrayCollection von endDate (Datum/Uhrzeit-Feld) in der Reihenfolge sortieren.

Siehe Lehre Dokumentation:

+1

Beachten Sie, dass dies mit dem EAGER-Abrufmodus nicht funktionieren wird: https://github.com/doctrine/doctrine2/issues/4256 – Aistis

Verwandte Themen