Faire un “Select DISTINCT …” sous Symfony avec Propel

Il n’est jamais inutile surtout quand on possède un grand jeu de données de pouvoir faire un SELECT DISTINCT dans ses requètes, pour le faire Propel possède pour les Criteria une méthode SetDistinct(), mais le problème c’est que cette méthode, dans le cas général, va générer le code SQL suivant :


SELECT DISTINCT individu_id, individu_nom, individu_prenom, .....

et qu’a posteriori la requète sera hydratée pour récupérer les Objets “Individu” qui seront bel et bien unique, vis-à-vis de tous leurs attributs, mais pas pour une colonne précise comme le nom par exemple.

Ce petit article va vous donner un moyen et une explication pour passer au delà de cette limitation qui va avec le fonctionnement normal de Propel.

Tout d’abord nous allons partir du principe que vous souhaitez récupérer dans la base de donnée tous les noms Uniques au sein de la table individu. Donc on commence a construire le Criteria :


$c = new Criteria();
$c->addSelectColumns(IndividuPeer::INDIVIDU_NOM);
$c->SetDistinct();

Seulement si après vous essayer de faire un doSelect, Propel ressortira une erreur d’offset, car lors de la tentative d’hydratation, il cherchera des colonnes qui n’existent pas dans notre Select, car la requète ainsi formée est bel et bien :


SELECT DISTINCT individu.individu_nom FROM individu;

Pour préciser à Propel que l’on ne veut que le résultat de la requête il ne faut donc pas faire un doSelect, mais ceci :


$individu = IndividuPeer::doSelectRS($c);
// ou dans symfony 1.2 :
$individu = IndividuPeer::doSelectStmt($c);
//on récupère alors les données dans la matrice associative $individu par :
echo $individu['individu_nom'];

voilà, vous savez tout, et ça vous évitera (pour cette fois) de finir par faire vos requêtes à la main, en bypassant l’ORM. 🙂