2009-10-27 3 views
12

ho bisogno di qualcosa di simile:Iterate Dottrina Collection ordinato da qualche campo

 $products = Products::getTable()->find(274); 
     foreach ($products->Categories->orderBy('title') as $category) 
     { 
      echo "{$category->title}<br />"; 
     } 

so che non è possibile, ma ... Come posso fare qualcosa di simile senza creare un Doctrine_Query?

Grazie.

risposta

9

Stavo solo guardando lo stesso problema. È necessario convertire il Doctrine_Collection in un array:

$someDbObject = Doctrine_Query::create()...; 
$children = $someDbObject->Children; 
$children = $children->getData(); // convert from Doctrine_Collection to array 

Quindi è possibile creare una funzione di ordinamento e chiamarlo:

// sort children 
usort($children, array(__CLASS__, 'compareChildren')); // fixed __CLASS__ 

Dove compareChildren sembra qualcosa di simile:

private static function compareChildren($a, $b) { 
    // in this case "label" is the name of the database column 
    return strcmp($a->label, $b->label); 
} 
+2

la soluzione ha funzionato solo quando l'ho cambiato in: usort ($ bambini, array (_____ CLASS_____, 'compareChildren')); – stoefln

31

È può anche fare:

$this->hasMany('Category as Categories', array(... 
      'orderBy' => 'title ASC')); 

Nel file di schema sembra che:

Relations: 
    Categories: 
     class: Category 
     .... 
     orderBy: title ASC 
+5

Se l'ordinamento è "permanente", utilizzare in questo modo è molto meglio che usare quello di Chris William. – avetisk

+2

Lo svantaggio è la permanenza. L'aggiunta di un ordine a OGNI query per questa relazione influirà sulle prestazioni. –

+0

o tramite annotazione '@ OrderBy': http://docs.doctrine-project.org/en/2.0.x/reference/annotations-reference.html#annref-orderby – zizoujab

3

Si potrebbe aggiungere una funzione di ordinamento per Colletion.php:

public function sortBy($sortFunction) 
{ 
    usort($this->data, $sortFunction); 
} 

Ordinamento un Doctrine_Collection di utenti per la loro età sarebbe simile a questa:

class ExampleClass 
{ 

    public static function sortByAge($a , $b) 
    { 
     $age_a = $a->age; 
     $age_b = $b->age; 

     return $age_a == $age_b ? 0 : $age_a > $age_b ? 1 : - 1; 
    }  

    public function sortExample() 
    { 
     $users = User::getTable()->findAll(); 
     $users ->sortBy('ExampleClass::sortByAge'); 

     echo "Oldest User:"; 
     var_dump ($users->end()); 
    } 

} 
9

Si potrebbe utilizzare collezione iteratore:

$collection = Table::getInstance()->findAll(); 

$iter = $collection->getIterator(); 
$iter->uasort(function($a, $b) { 
    $name_a = (int)$a->getName(); 
    $name_b = (int)$b->getName(); 

    return $name_a == $name_b ? 0 : $name_a > $name_b ? 1 : - 1; 
});   

foreach ($iter as $element) { 
    // ... Now you could iterate sorted collection 
} 

Se si desidera ordinare la raccolta con il metodo __toString, sarà molto più facile:

foreach ($collection->getIterator()->asort() as $element) { /* ... */ } 
+1

Provato usando '$ collection-> getIterator() -> asort()' ma restituisce semplicemente bool. –

+0

Scusa, ho dimenticato come funziona. Hai ragione, restituisce true in caso di successo e false in caso di fallimento. Un bel design. – temochka

+0

Le probabilità sono che se si chiama asort prima di iterare, si sarà in grado di scorrere l'elenco ordinato. –