Imaginons un modèle Script ayant une propriété category qui permet de classifier les différents scripts par catégorie. Si je veux récupérer toutes les catégories de scripts, le code que je vais écrire pourrait ressembler à ça :
public static function getCategories() {
$criteria = new Criteria();
$criteria->addGroupByColumn(self::CATEGORY);
return self::doSelect($criteria);
}
J'aurais pu aussi faire un "select distinct catgeory" mais pour les besoins suivants j'ai préféré faire un "group by". Je voudrais maintenant pour chaque catégorie de scripts savoir combien de scripts y sont associés pour afficher dans un menu. Toute ressemblance avec un menu existant n'est pas purement fortuite; mais c'est une autre histoire !
La requête sql serait toute simple :select category, count(*) as c from scripts group by category;
Il n'est pas possible de faire la même chose en tout objet. Il va falloir hydrater les objets résultats "à la main". On va commencer par ajouter la propriété count à notre object Script, ainsi que les méthodes pour renseigner (setCount) et récupérer (getCount) cette nouvelle propriété:
class Script extends BaseScript
{
protected $count = 0;
public function setCount($n) {
$this->count = $n;
}
public function getCount() {
return $this->count;
}
}
Voici maintenant le code pour symfony 1.2.* qui va permettre d'hydrater (c'est-à-dire de transformer chaque ligne de résultat en un objet Script :
public static function getCategories() {
$criteria = new Criteria();
self::addSelectColumns($criteria);
$criteria->addGroupByColumn(self::CATEGORY);
$criteria->addAsColumn('cnt', 'COUNT(*)');
$stmt = self::doSelectStmt($criteria);
$scripts = array();
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
$script = new Script;
$col = $script->hydrate($row);
$script->setCount(($row[$col] !== null) ? (int) $row[$col] : null);
$scripts[] = $script;
}
return $scripts;
}
Le code pour symfony 1.0.* et plus généralement les versions inférieures à 1.2 est légèrement différents car symopfy 1.2 se base désormais sur PDO:
Il va falloir remplacer la ligne :
$stmt = self::doSelectStmt($criteria);
par
$row = self::doSelectRs($criteria);
Et la ligne :
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
par
while ($row->next()) {
1 De Palleas -
Mmmh, il n'y a pas une erreur sur les ligne à remplacer à la fin de ton billet ? Ou alors je ne suis pas bon au jeu des différences :x
2 De Nicolas -
Merci. C'est corrigé. En récompense, je te mets ma nouvelle recette.
3 De Hugo -
Très intéressant ton article Nicolas. Il n'est jamais très évident au début de comprendre comment fonctionne l'hydratation des objets avec Propel. As-tu déjà essayé un peu Doctrine ?