2009-10-27 7 views
12

je besoin de quelque chose comme ceci:Itérer Collection Doctrine commandé par un champ

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

Je sais qu'il est impossible, mais ... Comment puis-je faire quelque chose comme ça, sans créer un Doctrine_Query?

Merci.

Répondre

9

Je regardais juste le même problème. Vous devez convertir le Doctrine_Collection dans un tableau:

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

Ensuite, vous pouvez créer une fonction de tri personnalisé et l'appeler:

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

Où compareChildren ressemble:

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

votre solution a fonctionné seulement quand je l'ai changé: usort (enfants $, array (_____ CLASS_____, 'compareChildren')) – stoefln

31

Vous peut également faire:

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

Dans votre fichier de schéma, il ressemble à:

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

Si le tri est "permanent", utiliser cette méthode est bien meilleur que celui de Chris William. – avetisk

+2

L'inconvénient est la permanence. Ajouter une commandeA chaque requête pour cette relation aura un impact sur les performances. –

+0

ou par l'annotation '@ OrderBy': http://docs.doctrine-project.org/fr/2.0.x/reference/annotations-reference.html#annref-orderby – zizoujab

3

Vous pouvez ajouter une fonction de tri à Colletion.php:

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

Tri un Doctrine_Collection des utilisateurs par leur âge ressemblerait à ceci:

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

Vous pouvez utiliser la collection iterator:

$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 
} 

Si vous voulez trier la collection en utilisant la méthode __toString, il sera beaucoup plus facile:

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

Essayé en utilisant '$ collection-> getIterator() -> asort()' mais il renvoie simplement bool. –

+0

Désolé, j'ai oublié comment cela fonctionne. Vous avez raison, il retourne vrai sur le succès et faux sur l'échec. Un si beau design. – temochka

+0

Les chances sont que si vous appelez avant d'itérer, vous pourrez parcourir la liste triée. –