Un exemple d'utilisation des classes XoopsObject et XoopsObjectHandler
par Oryxvet
et article présente une architecture minimale mais fonctionnelle de création / modification / liste des éléments d 'une table existante de BD. Il fait suite á la publication d'un article présentant les classes XoopsObject et XoopsObjectHandler.
1.1. Principe du MVC :
L'architecture présentée ici propose un architecture proche du fameux MVC (Modêle Vue Controlleur). Le MVC sert de trame á la description d'un exemple d'utilisation du pattern DAO developpé sous xoops. Le Modêle est représenté par la class DAO (répertoire Class) , la vue par le formulaire (répertoire /form) et le contrôleur par le programme index_Maclass.php mis á la racine.
L'index gêre á la fois l'affichage des données dans le formulaire et la réception des requêtes http issues de ce même formulaire (Le formulaire affiché par l'index est posté vers l'index).
1.2. Le Modêle :
Prenons l'exemple d'une table Client que j'ai appelle vxp_client. Suffixer le nom des tables par le nom du module les utilisant est une bonne habitude car cela permet d'en faire un groupe homogêne :
Pour avoir une class qui implante les classes XoopsObject et XoopsObjectHandler du pattern Data Access Objet on peux utiliser 3 maniêres :
1/ On peux la coder á la main
2/ On peux utiliser le concept de Mithrandir qui utilise une classe générique du handler http://dev.xoops.org/modules/xfsnippe ... ype=snippet&snippet_id=27 et ne code que le xoopsObjets
3/ On peux utiliser le module " class generator " afin de générer le fichier contenant ces 2 classes.
Nous utilisons ici class generator pour des raisons de simplicité. Un préalable á l'utilisation du class generator est que le module utilisant cette table soit déjá installé sous Xoops (les modules proposés dans l'IHM sont ceux déjá installés). Le module class generator est disponible sur dev.oryxvet.com et www.xoops.org . Il est en cours de validation sur www.frxoops.org.
La classe générée par le class generator est la suivante :
class vxp_client extends XoopsObject
{
var $db;
function vxp_client ($id=null)
{
$this->db =& Database::getInstance();
$this->initVar("client_id",XOBJ_DTYPE_INT,null,false,10);
$this->initVar("nom",XOBJ_DTYPE_TXTBOX, null, false);
$this->initVar("prenom",XOBJ_DTYPE_TXTBOX, null, false);
$this->initVar("adresse_ligne1",XOBJ_DTYPE_TXTBOX, null, false);
$this->initVar("adresse_ligne2",XOBJ_DTYPE_TXTBOX, null, false);
$this->initVar("adresse_cp",XOBJ_DTYPE_TXTBOX, null, false);
$this->initVar("adresse_commune",XOBJ_DTYPE_TXTBOX, null, false);
if ( !empty($id) ) {
if ( is_array($id) ) {
$this->assignVars($id);
} else {
$this->load(intval($id));
}
} else {
$this->setNew();
}
}
Etc ….
Pour plus d'information sur la description de ces 2 classes voir les 2 url suivant du wiki xoops :
http://dev.xoops.org/modules/phpwiki/index.php/XoopsObjectHandler
http://dev.xoops.org/modules/phpwiki/ ... php/XoopsObjectAndHandler
Notez que le nom des attributs est exactement la même que le nom des colonnes de la base de données.Nous avons donc notre Modêle du MVC via la class MonModule/class/vxp_client.php. Maintenant passons á la présentation de ce modêle dans une Vue.
1.3. La Vue
La vue est tout simplement le formulaire. L'utilisation des classes xoopsform dédiées á la création de formulaire (répertoire class\xoopsform) est la maniêre la plus rapide de créer un formulaire. Nous allons coder ce formulaire dans un fichier form_vxp_client.php afin de bien distinguer la vue du contrôleur.
Nous utilisons la convention de nom selon laquelle le nom des variables stockant la valeur des attributs est exactement le même que le nom de la colonne, le même que celle des " Vars " du xoopsobject.
Voici le fichier /form/form_vxp_client
<?php
include XOOPS_ROOT_PATH.'/modules/vetexpert/language/'.$xoopsConfig['language'].'/form_vxp_client.php';
1 Include_once XOOPS_ROOT_PATH.'/class/xoopsformloader.php';
$titre_form .=_FO_VXP_CLIENT;
2 $form = new GeneratorThemeForm($titre_form, 'form', 'index_vxp_client.php');
3 $f_id_hidden = new XoopsFormHidden("id", $client_id);
$form->addElement($f_id_hidden);
// ajout des actions
4 $op_hidden = new XoopsFormHidden('op', 'store');
$form->addElement($op_hidden);
$action_buttons = new XoopsFormElementTray("");
$submit_action = new XoopsFormButton('', 'action', _AC_GEN_VALIDER, 'submit');
$action_buttons->addElement($submit_action);
$form->addElement($action_buttons);
// ajout des champs
5 $f_prenom = new XoopsFormText(_FO_PRENOM, 'prenom',50,150,$prenom);
$form->addElement($f_prenom,true); // obligatoire
$f_nom = new XoopsFormText(_FO_NOM, 'nom',50,150,$nom);
$form->addElement($f_nom,true); // obligatoire
$f_adresse_ligne1 = new XoopsFormText(_FO_ADRESSE_LIGNE1, 'adresse_ligne1',50,150,$adresse_ligne1);
$form->addElement($f_adresse_ligne1);
$f_adresse_ligne2 = new XoopsFormText(_FO_ADRESSE_LIGNE2, 'adresse_ligne2',50,150,$adresse_ligne2);
$form->addElement($f_adresse_ligne2);
$f_adresse_cp = new XoopsFormText(_FO_ADRESSE_CP, 'adresse_cp',10,150,$adresse_cp);
$form->addElement($f_adresse_cp);
$f_adresse_commune = new XoopsFormText(_FO_ADRESSE_COMMUNE, 'adresse_commune',40,150,$adresse_commune);
$form->addElement($f_adresse_commune);
6 $form->display();
?>
Etudions le code :
- : Importation des classes xoopsform
- : Création du formulaire que l'on post vers l'index (index_vxp_client.php)
li>: Un champ caché stockant l'id de l'enregistrement est mis dans le formulaire. Cet id est la référence, la clé unique qui permet d'accéder á l'enregistrement de la BD lors de la soumission du formulaire vers l'index- : Les actions possibles sur ce formulaire sont intégrées. Ici nous n'en avons qu'une appelé store. On utilise ici l'élément XoopsFormElementTray qui permet d'ajouter plusieurs XoopsFormElement sur la même ligne
- : les champs de la class sont tour á tour intégrés
- : affichage du formulaire
1.4. Le contrôleur
Le contrôleur est représenté par l'index.php. Dans cette architecture, il y un contrôleur par class, dans notre exemple ce sera index_vxp_client.php. Les principes suivants ont été retenus. Si l'objet est en modification l'identifiant est passé dans la requête get c'est a dire á la fin de l'url sous la forme ?id=xxx. Dans le cas ou l'id n'est pas passé, on considêre que l'on est en création.
<?php
1 include 'header.php';
2 include XOOPS_ROOT_PATH.'/header.php';
3 include XOOPS_ROOT_PATH.'/modules/vetexpert/language/'.$xoopsConfig['language'].'/main.php';
4 include XOOPS_ROOT_PATH.'/modules/vetexpert/class/vxp_client.php';
5 include XOOPS_ROOT_PATH.'/modules/vetexpert/action/action_manager_vxp_client.php';
// request management
// ------------------
6 if (isset($_POST)) {
extract($_POST);
}
7 if (isset($_GET)) {
extract($_GET);
}
8 if (!(isset($op))) $op='';
9 if (!(isset($id))) $id='';
// creation du DAO vers vxp_client
// -------------------------------
10 if ($id) {
$handler_vxp_client = & xoops_gethandler('vxp_client');
$vxp_client = $handler_vxp_client->get($id);
$vxp_client->unsetNew();
} else {
$vxp_client = new vxp_client();
$vxp_client->setNew();
}
// action management
// ----------------
11 if ($op) {
if (isset($_POST)) { // chargement de l'objet pasr la requete
$vxp_client->setVars($_POST);
}
// execute the "op" fonction
$retour=$op($vxp_client);
$msg=$retour['msg'];
redirect_header('index_vxp_client.php?id='.$retour['id'],1,$msg);
}
12 foreach ($vxp_client->getVars() as $key => $value) {
if (isset($value['value'])) {
$$key = $value['value'];
}
}
13 include 'form/form_vxp_client.php';
include_once XOOPS_ROOT_PATH."/footer.php";
?>
Décrivons maintenant cet index :
6 et 7 : Chargement systématique des données issues du Get et des données issues du post en variable php. La fonction extract de PHP est ici bien utile, elle prend un tableau associatif en paramêtre et crée les variables dont les noms sont les index de ce tableau, et leur affecte la valeur associée.
8 et 9 : Ce code est mis afin de ne pas avoir de variable non définie (car de la création par exemple)
10 : Chargement de l'objet. Si l'id n'est pas fournit on considêre qu'il s'agit d'un nouvel objet.
11 : Ce code gêre le retour suite á validation du formulaire. On utilise la gestion des variables dynamique de PHP (Une variable dynamique prend la valeur d'une variable et l'utilise comme nom d'une autre variable). Ici la valeur de la variable $op est le nom de la fonction. Dans notre exemple, cette variable op est représenté par un champs caché aura la valeur " store ". La fonction store() sera donc exécutée.
12 : On décharge les valeurs des attributs de l'objet dans des variables afin qu'elle soit utilisé dans le formulaire
13 : Chargement du formulaire.
1.5. Une liste de clients á l'aide d'un template smarty
Il est três facile d'utiliser smarty avec la classe DAO. Il suffit d'assigner le tableau des " vars " comme variable utilisable par smarty. Je décris ci-dessous un exemple avec la liste de nos clients. Le programme liste_vxp_client.php utilise le template smarty liste_vxp_client.html.
<?php
include 'header.php';
include XOOPS_ROOT_PATH.'/header.php';
include XOOPS_ROOT_PATH.'/modules/vxp/class/vxp_client.php';
1 $xoopsOption['template_main'] = 'liste_vxp_client.html';
2 $xoopsTpl->assign(array(
"lang_nom" => _FO_VXP_NOM,
"lang_prenom" => _FO_VXP_PRENOM
));
3 $handler_vxp_client = & xoops_gethandler('vxp_client');
4 $clients = $handler_vxp_client->getObjects();
5 $xoopsTpl->assign('clients',$clients);
include_once XOOPS_ROOT_PATH."/footer.php";
?>
1 : description du template utilisé.
2 : Assignation des variables contenant les entêtes de colonnes
3 4 : recherches des clients á l'aide du handler de vxp_client.
5 : Assignation des clients
Le template doit être mis dans le répertoire /templates, il est le suivant :
<table class="outer" cellspacing="1" cellpadding="4">
<tr>
<th align="center"><{$lang_nom}></th><th align="center"><{$lang_prenom}></th>
</tr>
<{section name=i loop=$clients}>
<{if $smarty.section.i.index is even }><{assign var="class" value="even"}>
<{else}><{assign var="class" value="odd"}>
<{/if}>
<tr >
<td class="<{$class}>">
<a href="index_vxp_client.php?id=<{$clients[i]->getVar('client_id')}>">
<{$clients[i]->getVar('nom')}>
</a></td>
<td class="<{$class}>">
<{$clients[i]->getVar('prenom')}>
</td>
</tr>
<{/section}>
</table>
On utilise la capacité de smarty de faire référence aux propriétés d'un objet pour accéder aux informations
<{$clients[i]->getVar('client_id')}>. Voir le paragraphe relatif aux objets de la documentation de smarty.
Ce module de démonstration est téléchargeable ici module vxp_client