Section: Récupération de liste d'enregistrements DAO
« Utilisation d'une factory et d'un record DAO | ^ jDao : mapping objet relationnel | Ajouter des méthodes en XML » |
− Table des matières
Créer, modifier et supprimer des enregistrements dans une base de données est très utile. Mais c'est encore mieux si on peut les lire. Voici comment récupérer un ou plusieurs enregistrements.
Récupérer un seul enregistrement ¶
La méthode à utiliser avec la fabrique (factory), est get()
en lui donnant
la valeur de la clé primaire de l'enregistrement.
La méthode retourne directement l'objet correspondant à l'enregistrement. Chaque propriété de l'objet correspond à un champs de l'enregistrement, tel que c'est déclaré dans le fichier dao.
// instanciation de la factory
$maFactory = jDao::get("foo");
// récupération d'un record dont le contenu correspond
// à l'enregistrement ayant pour identifiant 3
$baz = $maFactory->get(3);
// récupération d'un des champs de l'enregistrement, ici par
// exemple si un champs id existe.
$id = $baz->id
Dans le cas où votre table comporte une clé multiple déclarée dans le fichier
XML du DAO au moyen de primarykey="cle1,cle2"
, vous devez donner toutes
les valeurs de la clé en même temps, comme ceci :
$maFactory = jDao::get("foo");
// 3 et 4 sont ici les valeurs respectives de cle1 et cle2
$baz = $maFactory->get(3, 4);
ou
$maFactory = jDao::get("foo");
// 3 et 4 sont ici les valeurs respectives de cle1 et cle2
$baz = $maFactory->get(array(3, 4));
- *Attention** : Il est impératif que l'ordre dans lequel sont passées les
valeurs soit le même que celui déclaré dans l'attribut
primarykey
. En bref,$maFactory->get(4, 3)
est bien différent de$maFactory->get(3, 4)
.
La méthode delete()
fonctionne de la même façon.
Récupérer une liste d'enregistrements ¶
Quand vous voulez récupérer tout les enregistrements, il faut utiliser
findAll()
. Cette méthode retourne un objet jDbResultSet
qui
permettra alors de récupérer un à un les enregistrements. Rappelez vous que
cette classe implémente l"interface Iterator, et est donc utilisable directement
dans un foreach
.
// instanciation de la factory
$maFactory = jDao::get("foo");
// récupération d'une liste complète de records de type foo
$liste = $maFactory->findAll();
foreach ($liste as $row) {
// $row contient un enregistrement
echo $row->id;
}
Vous pouvez aussi utiliser deux autres méthodes de jDbResultSet
. La
première est fetch()
, qui permet de récupérer un enregistrement, et avance
ensuite un "curseur" vers l'enregistrement suivant. Vous pouvez l'appeler alors
plusieurs fois de suite pour parcourir la liste des enregistrements.
// parcours de toute la liste
while ($row = $liste->fetch()) {
// $row contient un enregistrement
echo $row->id;
}
Vous avez aussi fetchAll()
qui permet de récupérer tout d'un seul coup
dans un tableau php.
$rows = $list->fetchAll();
foreach ($rows as $rowID => $row) {
echo $row->id;
}
Vous pouvez réaliser des méthodes de récupération personnalisées, en les spécifiant dans le fichier XML (voir DAO avancés).
Récupérer des records selon critères ¶
Les factory DAO mettent à disposition trois méthodes findBy()
,
countBy()
et deleteBy()
qui s'utilisent en leur passant un objet
jDaoConditions
, objets que vous récupérez avec jDao
. Voici un
exemple :
$conditions = jDao::createConditions();
$conditions->addCondition('libelle','=',$un_nom);
$conditions->addCondition('status','=',5);
$liste = $maFactory->findBy($conditions);
$count = $maFactory->countBy($conditions);
Tout comme findAll()
, findBy()
renvoie un objet jDbResultSet
qui permet de parcourir la liste des enregistrements qui correspondent aux
critères indiqués.
La méthode addCondition()
prend en paramètre un nom de propriété, un
opérateur (SQL), et une valeur.
Vous pouvez aussi indiquer un ordre de sélection avec la méthode
addItemOrder()
, et regrouper divers critères ensemble avec
startGroup()
et endGroup()
:
$conditions = jDao::createConditions();
// condition : libelle = $un_nom AND (status=5 OR status=4) ORDER BY libelle desc
$conditions->addCondition('libelle','=',$un_nom);
$conditions->startGroup('OR');
$conditions->addCondition('status','=',5);
$conditions->addCondition('status','=',4);
$conditions->endGroup();
$conditions->addItemOrder('libelle','desc');
$liste = $maFactory->findBy($conditions);
Pour ajouter une clause LIMIT, La méthode findBy()
prend en plus 2
paramètres optionnels: le numéro du premier enregistrement à récupérer (offset),
et le nombre d'enregistrement à renvoyer.
Par exemple pour récupérer les 15 premiers enregistrements :
$liste = $maFactory->findBy($conditions, 0, 15);
La méthode countBy()
quant à elle, prend un paramètre optionnel qui est le
nom de propriété du champ sur lequel on veut appliquer une clause DISTINCT, ce
qui donne par exemple:
// SELECT COUNT(DISTINCT table.libelle)...
$count = $maFactory->countBy($conditions, 'libelle');
Enfin, la méthode deleteBy()
permet d'effacer des enregistrements selon
critères et retourne le nombre de lignes effacées:
$nb_deleted = $maFactory->deleteBy($conditions);
Vous verrez que vous pouvez obtenir le même résultat via des méthodes dans le fichier XML. Cependant, l'utilisation de l'une ou l'autre des possibilités dépend du contexte.
Vous utiliserez jDaoConditions
lorsque que vous ne savez pas à l'avance le
nombre de critères et leur type. Cela peut être le cas suite à un formulaire de
recherche complexe, où l'utilisateur peut choisir ses critères. Vous utiliserez
aussi jDaoConditions
lorsque la recherche que vous faites n'est utilisée
qu'à un seul moment et rarement. En effet, les méthodes XML sont compilées en
PHP, et donc incluses à chaque fois que vous faites appel à la factory. Il n'est
peut-être pas utile d'inclure à chaque fois du code qui ne sert presque jamais.
Dans les autres cas, il est recommandé de passer par les méthodes XML, en particulier donc quand vous connaissez les critères à l'avance (sans forcément connaître leur valeur bien sûr), et que c'est une recherche souvent utilisée. En effet, jDao crée les requêtes SQL à l'avance dans la classe générée, ce qui évite construire les requêtes SQL à chaque fois qu'on les utilise, permettant alors de meilleurs performances globales.
Il arrive souvent par exemple de redéfinir la méthode findAll
en XML, pour
indiquer un ordre de récupération.
Les différents opérateurs SQL pris en compte ¶
Comme expliqué précédemment, la méthode addCondition()
prend en second
paramètre un opérateur SQL. Ce dernier prend en compte les opérateurs de
comparaison ainsi que les prédicats suivants :
- LIKE, NOT LIKE, ILIKE,
- IN, NOT IN,
- IS, IS NOT,
- IS NULL, IS NOT NULL,
- MATCH, REGEXP, NOT REGEXP, RLIKE, SOUNDS LIKE
~
,!~
,~*
,!~*
(operateurs pour les expressions régulières de postgresql)
Cas spéciaux avec des valeurs NULL ¶
Pour tester une valeur NULL ou non NULL, vous pouvez utiliser tout ce que SQL vous propose
(IS NULL, IS NOT, ...), même "=" ou "!=". N'oubliez pas de passer une valeur null
PHP
et non pas la chaine "NULL".
$conditions->addCondition('status','=', null); // equivalent à IS NULL
$conditions->addCondition('status','!=', null); // equivalent à IS NOT NULL
$conditions->addCondition('status','IS', null);
$conditions->addCondition('status','IS NOT', null);
$conditions->addCondition('status','IS NULL', null);
$conditions->addCondition('status','IS NOT NULL', null);
$conditions->addCondition('status','LIKE', null);
$conditions->addCondition('status','NOT LIKE', null);
...
Expressions régulières ¶
Pour les bases qui le supporte (postgresql par exemple), on peut indiquer une expression régulière.
Avec Postgresql, vous utiliserez ~
, !~
, ~*
, !~*
.
$conditions->addCondition('status','~', '^test');
...
Pour les autres bases, si elles le supportent, vous utiliserez REGEXP
ou NOT REGEXP
.
Classe personnalisée pour un enregistrement ¶
Si vous avez besoin d'ajouter des méthodes supplémentaires sur la classe générée d'un record, (pour par exemple calculer des valeurs à partir de champs), vous pouvez créer une classe contenant ces méthodes et la déclarer dans le dao.
Déclaration ¶
Pour déclarer une classe personnalisée, il vous suffira de renseigner l'attribut
extends
du tag record
votre dao:
<!-- fichier mymodule/daos/mydao.dao.xml -->
...
<record extends="mymodule~myrecord">
...
</record>
...
Creation ¶
La classe doit être stockée dans un fichier myrecord.daorecord.php
dans le
répertoire daos/
de votre module, et doit être défini de la manière suivante:
- l' enregistrement doit être déclaré via une classe abstraite
- le nom de cette classe est le nom choisi suivi du mot "DaoRecord"
- la classe doit hériter de la classe
jDaoRecordBase
// fichier mymodule/daos/myrecord.daorecord.php
abstract class myrecordDaoRecord extends jDaoRecordBase {
function calculateTotal() {
return $this->amount + $this->vat;
// ...
}
}
Ainsi, vous pourrez appeler cette methode sur n'importe quel enregistrement:
$maFactory = jDao::get("mymodule~myrecord");
$liste = $maFactory->findAll();
foreach ($liste as $row) {
$total = $row->calculateTotal();
//...
}