====== CRUD générique de base ====== Vous découvrirez dans cet article comment réaliser une petite application Jelix basée sur un [[fr:tutoriels:crud-jform-dao|CRUD]]. **ATTENTION : ce tutoriel est assez vieux, et n'utilise pas le controlleur jControllerDaoCrud fourni depuis jelix 1.0Beta3.1 qui simplifie beaucoup la tâche** (Voir [[:tutoriels:crud-jform-dao|l'autre tutoriel]]). **Le code comprend** : * Une classe CRUD (Create, Retrieve, Update, Delete) générique * Une classe d'utilisation du CRUD * Une personnalisation complète du CRUD :: ressources Jelix du CRUD et des messages * Une réponse HTML personnalisée * Trois templates associés aux actions du CRUD * Uniformisation de la mise en page et de la mise en forme en utilisant une CSS * Un code source bien documenté * Un code source facilement adaptable **Limites actuelles** * Le CRUD ne s'applique qu'à une seule table à la fois via le DAO * Les templates du CRUD et le fichier formulaire sont créés manuellement ===== Pré-requis ===== Étant donné qu'il y a des bugs dans jForms de la version 1.0 beta 2.1 de Jelix (rappel: jForms est étiqueté comme étant experimental dans cette version !), **les exemples de ce tutoriel ne fonctionnent qu'avec la version en cours de développement de jelix 1.0 beta 3** ([[fr:telechargement:|la version dites nightly]]). Par contre, il faudra faire quelques adaptations si vous utilisez jelix 1.0. Vous devez avoir fait le [[fr:tutoriels:minitutoriel|Mini tutoriel]] et le [[fr:tutoriels:jelixnews|Tutoriel principal]] ou être à l'aise avec Jelix. Nous utiliserons le même type d'installation que celle du [[fr:tutoriels:minitutoriel|Mini tutoriel]]. Nous vous conseillons fortement la lecture des articles concernant le [[http://docs.jelix.org/fr/manuel-1.0/jforms|formulaire]] et le [[http://docs.jelix.org/fr/manuel-1.0/daos|DAO]] du manuel de Jelix. ===== Création de l'application ===== Veillez suivre la démarche décrite dans l'article [[fr:tutoriels:first-steps|Étapes lors de la création d'une application Jelix]] en tenant compte des informations suivantes: Nom de l'application : news\\ Nom du module : news\\ basePath = "/jelix/news/www" ou selon votre configuration préférée. Il se peut que cette table existe déjà dans votre base de données, sinon créez là. CREATE TABLE `news` ( `id_news` int(11) NOT NULL auto_increment, `sujet` varchar(255) NOT NULL, `texte` text NOT NULL, `news_date` date NOT NULL, PRIMARY KEY (`id_news`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; Ressource jDao : news~news\\ Fichier DAO : news\\ Table : news Créez dans le répertoire jelix/news/modules/news/forms/, le fichier //news.form.xml//.
===== Notes sur l'application à réaliser ===== Précisons l'ouvrage qu'il nous reste à faire pour compléter notre programme : * Une réponse HTML personnalisée (//myHtmlResponse.class.php//) * Le template principal (//main.tpl//) * Le CSS (//screen.css//) * La classe nommée //baseCrudController// (le CRUD) qui dérive de jController * Un exemple d'utilisation nommé defaultCtrl qui hérite de la classe du CRUD * Trois templates du CRUD correspondant à certaines actions Et nous aurons une fois terminé une application de base pouvant évoluer vers un projet informatique. ===== La réponse HTML ===== Le but de créer une réponse HTML personnalisée est de généraliser dans l'application : *utiliser le même thème dans toutes les pages de notre petite application *garantir l'initialisation par défaut de certaines variables *et de l'utilisation d'un template principal par défaut indépendant du CRUD Enregistrez le code suivant dans le fichier //jelix/news/responses/myHtmlResponse.class.php// body->assignIfNone('MAIN','

Aucun contenu

'); $this->body->assignIfNone('CRUDtpl',''); $this->addCSSLink($GLOBALS['gJConfig']->urlengine['basePath'].'screen.css'); } } ?>
Consulter le manuel pour obtenir plus de détail sur la classe [[http://docs.jelix.org/fr/manuel-1.0/creer_response|jReponseHTML]]. Pour indiquer à Jelix que vous avez créé une réponse personnalisée, vous devez ouvrir le fichier //jelix/news/var/config/index/config.ini.php// et ajouter **dans la section [responses]** la ligne suivante: html = myhtmlResponse ===== La CSS ===== Le fichier screen.css doit être enregistré dans jelix/news/www/ ou dans un de ses sous-répertoires. Ce fichier est le CSS contenu dans l'application **testapp** de Jelix. body { font-family: Verdana, Arial, Sans; font-size:0.8em;} a img { border:0;} pre { padding-left:1em; border-left:4px solid #efe03b; color:black; } #header { margin:20px 0 0 190px; width:730px; padding:15px; background-color:#1e92af; -moz-border-radius:10px 10px 0 0; /*height:35px;*/ color:white; font-weight:bold; font-size:1.5em; } #main {clear:both; margin:0 0 0 190px; padding:30px 15px 15px 15px; max-width:730px; color : #002830; border-left:1px solid #d8e1e4; border-right:1px solid #d8e1e4; max-width:728px; } #main a { color:#0594c8; text-decoration:underline; } #main a:visited { color : #002830;} #main a:hover { color: white; background-color: #0594c8; text-decoration:none;} #main a.wikilink2 { color:#ed5a02;} #main h1 { color: #3c90af; border-bottom:4px solid #ed5a02; margin:0; } #main h2 { color: #3c90af; border-bottom:2px solid #002830; margin:1em 0 0.5em 0; } #main h3 { color: #002830; border-bottom:1px solid #002830; margin:1em 0 0.5em 0; } #main h4 { color: #002830; } #main input.button{ background-color:#4397b6; border-left: 1px solid #99cbde; border-right: 1px solid #225365; border-top: 1px solid #99cbde ; border-bottom: 1px solid #225365; -moz-border-radius:3px; color:white; cursor: pointer; } .fail { color: red; } .pass { color: green; } pre { background-color: lightgray; } .resultfail { padding: 8px; margin-top: 1em; background-color: red; color: white; } .resultsuccess { padding: 8px; margin-top: 1em; background-color: green; color: white; } div.exception { margin-top:4px; margin-bottom:4px; background-color: #ff9186; border: 1px solid red; } div.exception strong {color: red;} div.exception p { font-size:0.9em; } .diff { background: white; border: 1px solid black; } .diff .block { background: #ccc; padding-left: 1em; } .diff .context { background: white; border: none; } .diff .block tt { font-weight: normal; font-family: monospace; color: black; margin-left: 0; border: none; } .diff del, .diff ins { font-weight: bold; text-decoration: none; } .diff .original, .diff .deleted, .diff .final, .diff .added { background: white; } .diff .original, .diff .deleted { background: #fcc; border: none; } .diff .final, .diff .added { background: #cfc; border: none; } .diff del { background: #f99; } .diff ins { background: #9f9; } #sidemenu { position:absolute; top:0; left:0; width:185px; padding-left:10px; } #sidemenu a {color:#0594c8; text-decoration:none;} #sidemenu a:hover { text-decoration: underline; } #sidemenu h1 { text-align:center; } #sidemenu h1 a {text-decoration:none;} #sidemenu h1 a:hover { text-decoration:none; } #sidemenu ul { margin:0 0 0 1em; padding:0 0 0 1em; color: #3c90af; } #sidemenu ul li { margin:0; padding:0 0 0 0em; } #sidemenu .userinfo { margin:2em 0; } #sidemenu p { text-align:center;} #footer { clear:both; margin:0 0 0 190px; padding:15px; max-width:728px; color : #002830; text-align:center; min-height:2em; background-color:#d8e1e4; border-left:1px solid #d8e1e4; border-right:1px solid #d8e1e4; border-bottom:1px solid #d8e1e4; -moz-border-radius:0px 0px 15px 15px; } ===== La classe du CRUD ===== Le classe baseCRUD contient tout le code directement lié à la manipulation des données d'une table. * Browse : Affiche tous les enregistrements d'une table * Create : Prépare la création d'un nouvel enregistrement * Update : Prépare la mise à jour d'un enregistrement * save : Sauvegarde un enregistrement * View : Affiche un enregistrement * Delete : Efface un enregistrement d'une table Au début de la classe on retrouve le nom des sélecteurs et des templates utilisés par le CRUD mais initialisés par la classe fille. Viens par après les messages qu'on peut considérer comme par défaut, puisque la classe fille peut les modifier. Le CRUD crée un template qui contiendra les messages et les données. Puis ce template sera inséré dans le template principal par le biais de la variable de template CRUDtpl. Vous devez enregistrer ce code dans le répertoire //jelix/news/modules/news/controllers/// et le fichier se nomme //baseCrudController.php//. 'La liste des fiches ',); protected $CRUD_txt_create = array( 'title' => 'Ajout d\'une fiche ',); protected $CRUD_txt_update = array( 'title' => 'Edition d\'une fiche ', 'errID' => 'L\'enregistrement que vous recherchez n\'existe pas. ',); protected $CRUD_txt_save = array( 'errTitle' => 'Erreur de session! ou session fermé', 'errMessage' => 'Les données session recherchées n\'existent pas',); protected $CRUD_txt_view = array( 'title' => 'La fiche ',); // Le réponse de l'action est-elle du type HTML ou est-ce une redirection? private $__typeReponseHTML = false; public function __construct($request){ parent::__construct($request); } /** * Récupère plusieurs enregistrements de la db */ protected function crud_browse(){ // Prépare la réponse $rep = $this->getResponse('html'); // Crée un template CRUD qui contiendra les données $tpl = new jTpl(); $tpl->assign('title', $this->CRUD_txt_browse['title']); // On récupère les données de la db $fact = jDao::get($this->CRUD_sel_jDao); $tpl->assign('liste', $fact->findAll()); // La validation d'une liste vide se fait dans la vue. // Insertion du template CRUD dans le template de l'action $rep->body->assign('CRUDtpl', $tpl->fetch($this->CRUD_tpl_browse)); return $rep; } /** * Ajoute un nouvel enregistrement dans la db */ protected function crud_create(){ // Si le jForms n'existe pas on le crée $form = jForms::get($this->CRUD_sel_jForm); if($form == null){ $form = jForms::create($this->CRUD_sel_jForm); } // Prépare la réponse $rep = $this->getResponse('html'); // Crée un template CRUD qui contiendra les données $tpl = new jTpl(); $tpl->assign('title', $this->CRUD_txt_create['title']); // Insère les données du formulaire dans le template CRUD $tpl->assign('form', $form->getContainer()); // Insertion du template CRUD dans le template de l'action $rep->body->assign('CRUDtpl', $tpl->fetch($this->CRUD_tpl_edit)); return $rep; } /** * Préparation de la saisie de données du formulaire html * Paramètres : * id : la clé du formulaire qui est aussi la clé primaire de notre enregistrement */ protected function crud_update(){ // Préparation de la réponse $rep = $this->getResponse('html'); // Si le jForms n'existe pas on le crée $form = jForms::get($this->CRUD_sel_jForm, $this->param('id')); if($form == null){ $form = jForms::create($this->CRUD_sel_jForm, $this->param('id')); } // On récupère les données de la db try { $form->initFromDao($this->CRUD_sel_jDao); }catch(Exception $e){ //quand initFromDao ne trouve pas l'enregistrement, il y a une exception $rep->title = $this->CRUD_txt_update['title']; $rep->body->assign('CRUDtpl', $this->CRUD_txt_update['errID']); return $rep; } // Un nouveau template qui contiendra les données $tpl = new jTpl(); $tpl->assign('title', $this->CRUD_txt_update['title']); // Insère les données du formulaire dans le template CRUD $tpl->assign('form', $form->getContainer()); // Insertion du template dans le template de l'action $rep->body->assign('CRUDtpl', $tpl->fetch($this->CRUD_tpl_edit)); return $rep; } /** * Enregistre le formulaire (jForm) * paramètres : * id : la clé du formulaire qui est aussi la clé primaire de notre enregistrement * La validation de données sera complétée dans la version beta 3... */ protected function crud_save(){ // On récupère les données de la session courante $form = jForms::fill($this->CRUD_sel_jForm, $this->param('id')); if(!$form){ // pas de formulaire ! // Préparation de la réponse de type html $rep = $this->getResponse("html"); $__typeReponseHTML = true; // Un nouveau template qui contiendra les données $tpl = new jTpl(); $tpl->assign('title', $this->CRUD_txt_save['errTitle']); $tpl->assign('message', $this->CRUD_txt_save['errMessage']); // Insertion du template dans le template de l'action $rep->body->assign('CRUDtpl', $tpl->fetch($this->CRUD_tpl_index)); return $rep; } //normalement, on devrait utiliser $form->check() pour vérifier le contenu du formulaire //mais cette méthode n'est pas complètement implanté. Donc on vérifie à la main if($form->getData('sujet') != '' && $form->getData('texte') != ''){ $form->saveToDao($this->CRUD_sel_jDao); }else{ // la vérification a échouée, // Retourne les données vers le client pour correction $rep = $this->getResponse("redirect"); $rep->params['id'] = $this->param('id'); if($this->param('id')){ $rep->action = $this->CRUD_sel_direct_update; }else{ $rep->action = $this->CRUD_sel_direct_create; } return $rep; } // La sauvegarde des données à réussi, // on va maintenant effacer le formulaire en session jForms::destroy($this->CRUD_sel_jForm, $this->param('id')); // on retourne à la liste $rep = $this->getResponse("redirect"); $rep->action = $this->CRUD_sel_direct_browse; return $rep; } /** * Affiche un enregistrement de la db * paramètres : * id : la clé de notre enregistrement */ protected function crud_view(){ // Préparation de la réponse $rep = $this->getResponse('html'); // On récupère les données de la db $fact = jDao::get($this->CRUD_sel_jDao); $rec = $fact->get($this->param('id')); // La validation d'une liste vide se fera dans la vue. // Un nouveau template qui contiendra les données $tpl = new jTpl(); $tpl->assign('title', $this->CRUD_txt_view['title']); $tpl->assign('rec', $rec); // Insertion du template dans le template de l'action $rep->body->assign('CRUDtpl', $tpl->fetch($this->CRUD_tpl_view)); return $rep; } /** * Efface l'enregistrement * paramètres : * id : la clé de notre enregistrement */ protected function crud_destroy(){ // Récupère un objet jDao $dao = jDao::get($this->CRUD_sel_jDao); // Détruit l'enregistrement correspondant à l'id $dao->delete($this->param('id')); // on retourne à la liste $rep = $this->getResponse("redirect"); $rep->action = $this->CRUD_sel_direct_browse; return $rep; } /** * Dans une action retourne vrai si la réponse utilisé est du type HTML */ protected function checkReponseHTML(){ return $this->__typeReponseHTML; } } ?> ===== Le controleur ===== Nous voici rendu au controleur qui utilise notre CRUD, la classe fille, la classe qui hérite du CRUD. C'est aussi cette classe qu'on appelle les fonctions qui manipulent les enregistrements de la table. Au début du controleur on retrouve un message qui sera affiché par l'action index. Remarquez le constructeur qui a exactement la même signature que sa classe parente qui elle aussi à la même signature que sa classe parente. Également le constructeur initialise les sélecteurs et les templates du CRUD. De plus le choix du template principal et du css a été fait dans la réponse personnalisée. Voir une section précédente. Vous devez copier le code suivant dans le fichier //jelix/news/modules/news/controllers/default.classic.php// getModulePath('news').'controllers/baseCrudController.php'; class defaultCtrl extends baseCrudController{ private $my_msg_index = 'Jelix vous présente un exemple de CRUD inscrit dans une classe de base.

Veillez noter que les exemples de ce tutoriel ne fonctionnent qu’avec la version en cours de développement de jelix 1.0 beta 3.

Le code comprend :
Limites présentement
'; public function __construct($request){ parent::__construct($request); $this->common(); } /** * Initialisation du CRUD */ private function common(){ $this->CRUD_sel_jDao = 'news~news'; $this->CRUD_sel_jForm = 'news'; $this->CRUD_sel_direct_browse = 'news~default_browse'; $this->CRUD_sel_direct_update = 'news~default_update'; $this->CRUD_sel_direct_create = 'news~default_create'; $this->CRUD_tpl_browse = 'news~crudbrowse'; $this->CRUD_tpl_edit = 'news~crudedit'; $this->CRUD_tpl_view = 'news~crudview'; } /** * Action par défaut... */ public function index(){ $rep = $this->getResponse('html'); $rep->body->assign('MAIN', $this->my_msg_index); return $rep; } /** * Exemple d'utilisation du CRUD * Récupère plusieurs enregistrements de la db */ public function browse(){ // CRUD $rep = $this->crud_browse(); // Votre formulaire $rep->body->assign('MAIN', 'Template d\'utilisation du CRUD action browse....'); return $rep; } /** * Exemple d'utilisation du CRUD * Préparation de la saisie de nouvelles données du formulaire html */ public function create(){ // CRUD $rep = $this->crud_create(); // Votre formulaire $rep->body->assign('MAIN', 'Template d\'utilisation du CRUD action create....'); return $rep; } /** * Exemple d'utilisation du CRUD * Préparation de la modification de données du formulaire html */ public function update(){ // CRUD $rep = $this->crud_update(); // Votre formulaire $rep->body->assign('MAIN', 'Template d\'utilisation du CRUD action update....'); return $rep; } /** * Exemple d'utilisation du CRUD * Ajoute ou modifie un enregistrement dans la db */ public function save(){ // CRUD $rep = $this->crud_save(); // Votre formulaire // Les réponses "html et redirect" n'ont pas les mêmes propriétés if($this->checkReponseHTML()){ $rep->body->assign('MAIN', 'Template d\'utilisation du CRUD action save....'); } return $rep; } /** * Exemple d'utilisation du CRUD * Affiche un enregistrement de la db */ public function view(){ // CRUD $rep = $this->crud_view(); // Votre formulaire $rep->body->assign('MAIN', 'Template d\'utilisation du CRUD action view....'); return $rep; } /** * Exemple d'utilisation du CRUD * Efface l'enregistrement dans la db */ public function destroy(){ // CRUD $rep = $this->crud_destroy(); return $rep; } } ?>
===== Le template main.tpl ===== Il s'agit du template principal qui affiche les templates du CRUD par le biais de la variable de template $CRUDtpl. Vous devez copier le code ci-dessous dans le fichier template nommé //main.tpl// du répertoire ///jelix/news/modules/news/templates///.
{$MAIN} {$CRUDtpl}

Sommaire

===== Le template crudview.tpl ===== Il s'agit du template du CRUD qui affiche un enregistrement. Vous devez copier le code ci-dessous dans le fichier template nommé //crudview.tpl// du répertoire ///jelix/news/modules/news/templates///.

{$title}


{if $rec}
id_news :
{$rec->id_news}
Sujet :
{$rec->sujet|escxml}
Texte :
{$rec->texte|escxml}
Date :
{$rec->news_date}
{else}

Cette fiche n'existe pas!

{/if}
===== Le template crudedit.tpl ===== Il s'agit du template du CRUD qui permet l'édition d'un enregistrement. Vous devez copier le code ci-dessous dans le fichier template nommé //crudedit.tpl// du répertoire ///jelix/news/modules/news/templates///.

{$title}


Votre identité

===== Le template crudbrowse.tpl ===== Il s'agit du template du CRUD qui affiche plusieurs enregistrements. Vous devez copier le code ci-dessous dans le fichier template nommé //crudbrowse.tpl// du répertoire ///jelix/news/modules/news/templates///.

{$title}


{if $liste->rowCount()} {foreach $liste as $rec} {/foreach}
{$rec->id_news} {$rec->sujet|escxml} {$rec->texte|escxml} {$rec->news_date} voir éditer détruire
{else}

Il y a aucune fiches d'enregistrés

{/if}
---- * [[fr:tutoriels:|Retour au sommaire des tutoriels]]