Piste :
Différences ¶
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédenteProchaine révisionLes deux révisions suivantes | ||
tutoriels:crud-generic [2007/08/30 08:57] – laurent | tutoriels:crud-generic [2007/12/17 11:07] – laurent | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | ====== CRUD générique de base ====== | ||
- | Vous découvrirez dans cet article comment réaliser une petite application Jelix basée sur un [[tutoriels: | ||
- | |||
- | **Le code comprend** : | ||
- | * Une classe CRUD (Create, Retrieve, Update, Delete) générique | ||
- | * Une classe d' | ||
- | * Une personnalisation complète du CRUD :: ressources Jelix du CRUD et des messages | ||
- | * Une réponse html personnalisé | ||
- | * Trois templates associée aux actions du CRUD | ||
- | * Uniformisation de la mise en page et de la mise en forme en utilisant un css | ||
- | * Un code source bien documenté | ||
- | * Un code source facilement adaptable | ||
- | |||
- | **Limites présentement** | ||
- | * Le CRUD ne s' | ||
- | * 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' | ||
- | |||
- | Vous devez avoir fait le [[manuel: | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | ===== Création de l' | ||
- | Veillez suivre la démarche décrite dans l' | ||
- | |||
- | Nom de l' | ||
- | Nom du module : news\\ | ||
- | |||
- | basePath = "/ | ||
- | |||
- | Il se peut que cette table existe déjà dans votre base de données, sinon créez là. | ||
- | |||
- | <code sql> | ||
- | |||
- | 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/ | ||
- | |||
- | <code html> | ||
- | |||
- | <?xml version=" | ||
- | <forms xmlns=" | ||
- | < | ||
- | < | ||
- | </ | ||
- | < | ||
- | < | ||
- | </ | ||
- | < | ||
- | < | ||
- | </ | ||
- | < | ||
- | < | ||
- | </ | ||
- | </ | ||
- | |||
- | </ | ||
- | |||
- | |||
- | |||
- | |||
- | ===== Notes sur l' | ||
- | Précisons l' | ||
- | |||
- | * Une réponse html personnalisée (// | ||
- | * Le template principal (// | ||
- | * Le css (// | ||
- | * La classe nommée // | ||
- | * Un exemple d' | ||
- | * 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' | ||
- | *utiliser le même thème dans toutes les pages de notre petite application | ||
- | *garantir l' | ||
- | *et de l' | ||
- | |||
- | Enregistrez le code suivant dans le fichier // | ||
- | <code php> | ||
- | |||
- | <? | ||
- | |||
- | require_once (JELIX_LIB_RESPONSE_PATH.' | ||
- | |||
- | class myHtmlResponse extends jResponseHtml { | ||
- | |||
- | | ||
- | |||
- | // modifications communes aux actions utilisant cette reponses | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | } | ||
- | } | ||
- | ?> | ||
- | |||
- | </ | ||
- | |||
- | Consulter le manuel pour obtenir plus de détail sur la classe [[http:// | ||
- | |||
- | Pour indiquer à Jelix que vous avez créé une réponse personnalisée, | ||
- | |||
- | <code ini> | ||
- | html = myhtmlResponse | ||
- | </ | ||
- | |||
- | ===== La CSS ===== | ||
- | Le fichier screen.css doit être enregistré dans jelix/ | ||
- | |||
- | |||
- | <code css> | ||
- | |||
- | body { font-family: | ||
- | a img { border:0;} | ||
- | pre { | ||
- | padding-left: | ||
- | border-left: | ||
- | color: | ||
- | } | ||
- | #header { | ||
- | margin:20px 0 0 190px; | ||
- | padding: | ||
- | background-color:# | ||
- | -moz-border-radius: | ||
- | / | ||
- | color: | ||
- | font-weight: | ||
- | font-size: | ||
- | } | ||
- | #main {clear: | ||
- | margin:0 0 0 190px; | ||
- | padding: | ||
- | max-width: | ||
- | color : #002830; | ||
- | border-left: | ||
- | border-right: | ||
- | max-width: | ||
- | } | ||
- | #main a { color:# | ||
- | #main a:visited { color : #002830;} | ||
- | #main a:hover { color: white; background-color: | ||
- | #main a.wikilink2 { color:# | ||
- | #main h1 { color: #3c90af; border-bottom: | ||
- | #main h2 { color: #3c90af; border-bottom: | ||
- | #main h3 { color: #002830; border-bottom: | ||
- | #main h4 { color: #002830; } | ||
- | #main input.button{ | ||
- | background-color:# | ||
- | border-left: | ||
- | border-right: | ||
- | border-top: 1px solid #99cbde ; | ||
- | border-bottom: | ||
- | -moz-border-radius: | ||
- | color: | ||
- | cursor: pointer; | ||
- | } | ||
- | .fail { color: red; } | ||
- | .pass { color: green; } | ||
- | pre { background-color: | ||
- | .resultfail { | ||
- | padding: 8px; margin-top: 1em; background-color: | ||
- | } | ||
- | .resultsuccess { | ||
- | padding: 8px; margin-top: 1em; background-color: | ||
- | } | ||
- | div.exception { margin-top: | ||
- | background-color: | ||
- | border: 1px solid red; | ||
- | } | ||
- | div.exception strong {color: red;} | ||
- | div.exception p { font-size: | ||
- | .diff { background: white; border: 1px solid black; } | ||
- | .diff .block { background: #ccc; padding-left: | ||
- | .diff .context { background: white; border: none; } | ||
- | .diff .block tt { font-weight: | ||
- | margin-left: | ||
- | } | ||
- | .diff del, .diff ins { font-weight: | ||
- | .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: | ||
- | top:0; | ||
- | left:0; | ||
- | width: | ||
- | padding-left: | ||
- | } | ||
- | #sidemenu a {color:# | ||
- | #sidemenu a:hover { text-decoration: | ||
- | #sidemenu h1 { text-align: | ||
- | #sidemenu h1 a {text-decoration: | ||
- | #sidemenu h1 a:hover { text-decoration: | ||
- | #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: | ||
- | #footer { | ||
- | clear:both; | ||
- | margin:0 0 0 190px; | ||
- | padding: | ||
- | max-width: | ||
- | color : #002830; | ||
- | text-align: | ||
- | min-height: | ||
- | background-color:# | ||
- | border-left: | ||
- | border-right: | ||
- | border-bottom: | ||
- | -moz-border-radius: | ||
- | } | ||
- | |||
- | </ | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | ===== 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 // | ||
- | <code php> | ||
- | |||
- | <?php | ||
- | |||
- | class baseCrudController extends jController{ | ||
- | | ||
- | // Les sélecteurs | ||
- | protected $CRUD_sel_jDao; | ||
- | protected $CRUD_sel_jForm; | ||
- | // Redirections | ||
- | protected $CRUD_sel_direct_browse; | ||
- | protected $CRUD_sel_direct_update; | ||
- | protected $CRUD_sel_direct_create; | ||
- | |||
- | // Les templates du CRUD | ||
- | protected $CRUD_tpl_browse; | ||
- | protected $CRUD_tpl_edit; | ||
- | protected $CRUD_tpl_view; | ||
- | | ||
- | // Les messages du CRUD | ||
- | protected $CRUD_txt_browse = array( ' | ||
- | protected $CRUD_txt_create = array( ' | ||
- | protected $CRUD_txt_update = array( ' | ||
- | ' | ||
- | protected $CRUD_txt_save | ||
- | ' | ||
- | protected $CRUD_txt_view | ||
- | | ||
- | // Le réponse de l' | ||
- | private $__typeReponseHTML = false; | ||
- | |||
- | public function __construct($request){ | ||
- | parent:: | ||
- | } | ||
- | |||
- | |||
- | /** | ||
- | * Récupère plusieurs enregistrements de la db | ||
- | */ | ||
- | protected function crud_browse(){ | ||
- | // Prépare la réponse | ||
- | $rep = $this-> | ||
- | | ||
- | // Crée un template CRUD qui contiendra les données | ||
- | $tpl = new jTpl(); | ||
- | $tpl-> | ||
- | // On récupère les données de la db | ||
- | $fact = jDao:: | ||
- | $tpl-> | ||
- | // La validation d'une liste vide se fait dans la vue. | ||
- | | ||
- | // Insertion du template CRUD dans le template de l' | ||
- | $rep-> | ||
- | | ||
- | return $rep; | ||
- | } | ||
- | | ||
- | /** | ||
- | * Ajoute un nouvel enregistrement dans la db | ||
- | */ | ||
- | protected function crud_create(){ | ||
- | // Si le jForms n' | ||
- | $form = jForms:: | ||
- | if($form == null){ | ||
- | $form = jForms:: | ||
- | } | ||
- | |||
- | // Prépare la réponse | ||
- | $rep = $this-> | ||
- | | ||
- | // Crée un template CRUD qui contiendra les données | ||
- | $tpl = new jTpl(); | ||
- | $tpl-> | ||
- | // Insère les données du formulaire dans le template CRUD | ||
- | $tpl-> | ||
- | | ||
- | // Insertion du template CRUD dans le template de l' | ||
- | $rep-> | ||
- | | ||
- | 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-> | ||
- | |||
- | // Si le jForms n' | ||
- | $form = jForms:: | ||
- | if($form == null){ | ||
- | $form = jForms:: | ||
- | } | ||
- | | ||
- | // On récupère les données de la db | ||
- | try { | ||
- | $form-> | ||
- | }catch(Exception $e){ | ||
- | //quand initFromDao ne trouve pas l' | ||
- | $rep-> | ||
- | $rep-> | ||
- | return $rep; | ||
- | } | ||
- | |||
- | // Un nouveau template qui contiendra les données | ||
- | $tpl = new jTpl(); | ||
- | $tpl-> | ||
- | // Insère les données du formulaire dans le template CRUD | ||
- | $tpl-> | ||
- | |||
- | // Insertion du template dans le template de l' | ||
- | $rep-> | ||
- | | ||
- | 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:: | ||
- | if(!$form){ | ||
- | // pas de formulaire ! | ||
- | // Préparation de la réponse de type html | ||
- | $rep = $this-> | ||
- | $__typeReponseHTML = true; | ||
- | |||
- | // Un nouveau template qui contiendra les données | ||
- | $tpl = new jTpl(); | ||
- | $tpl-> | ||
- | $tpl-> | ||
- | | ||
- | // Insertion du template dans le template de l' | ||
- | $rep-> | ||
- | |||
- | return $rep; | ||
- | } | ||
- | | ||
- | // | ||
- | //mais cette méthode n'est pas complètement implanté. Donc on vérifie à la main | ||
- | if($form-> | ||
- | $form-> | ||
- | }else{ | ||
- | // la vérification a échouée, | ||
- | // Retourne les données vers le client pour correction | ||
- | $rep = $this-> | ||
- | $rep-> | ||
- | if($this-> | ||
- | $rep-> | ||
- | }else{ | ||
- | $rep-> | ||
- | } | ||
- | | ||
- | return $rep; | ||
- | } | ||
- | | ||
- | // La sauvegarde des données à réussi, | ||
- | // on va maintenant effacer le formulaire en session | ||
- | jForms:: | ||
- | |||
- | // on retourne à la liste | ||
- | $rep = $this-> | ||
- | $rep-> | ||
- | |||
- | 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-> | ||
- | |||
- | // On récupère les données de la db | ||
- | $fact = jDao:: | ||
- | $rec = $fact-> | ||
- | // La validation d'une liste vide se fera dans la vue. | ||
- | | ||
- | // Un nouveau template qui contiendra les données | ||
- | $tpl = new jTpl(); | ||
- | $tpl-> | ||
- | $tpl-> | ||
- | |||
- | // Insertion du template dans le template de l' | ||
- | $rep-> | ||
- | | ||
- | return $rep; | ||
- | } | ||
- | |||
- | /** | ||
- | * Efface l' | ||
- | * paramètres : | ||
- | * id : la clé de notre enregistrement | ||
- | */ | ||
- | protected function crud_destroy(){ | ||
- | // Récupère un objet jDao | ||
- | $dao = jDao:: | ||
- | // Détruit l' | ||
- | $dao-> | ||
- | |||
- | // on retourne à la liste | ||
- | $rep = $this-> | ||
- | $rep-> | ||
- | | ||
- | return $rep; | ||
- | } | ||
- | |||
- | /** | ||
- | * Dans une action retourne vrai si la réponse utilisé est du type HTML | ||
- | */ | ||
- | protected function checkReponseHTML(){ | ||
- | | ||
- | return $this-> | ||
- | | ||
- | } | ||
- | | ||
- | } | ||
- | ?> | ||
- | |||
- | </ | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | ===== 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' | ||
- | |||
- | 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. | ||
- | |||
- | |||
- | Vous devez copier le code suivant dans le fichier // | ||
- | <code php> | ||
- | |||
- | <?php | ||
- | global $gJCoord; | ||
- | include $gJCoord-> | ||
- | class defaultCtrl extends baseCrudController{ | ||
- | | ||
- | private $my_msg_index = 'Jelix vous présente un exemple de CRUD inscrit dans une classe de base.<br /><br /> | ||
- | 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.<br /><br /> | ||
- | Le code comprend : | ||
- | <ul> | ||
- | < | ||
- | < | ||
- | < | ||
- | < | ||
- | < | ||
- | < | ||
- | < | ||
- | < | ||
- | </ul> | ||
- | <br /> | ||
- | < | ||
- | <ul> | ||
- | < | ||
- | < | ||
- | </ul> | ||
- | '; | ||
- | |||
- | public function __construct($request){ | ||
- | parent:: | ||
- | $this-> | ||
- | } | ||
- | | ||
- | /** | ||
- | * Initialisation du CRUD | ||
- | */ | ||
- | private function common(){ | ||
- | $this-> | ||
- | $this-> | ||
- | $this-> | ||
- | $this-> | ||
- | $this-> | ||
- | $this-> | ||
- | $this-> | ||
- | $this-> | ||
- | } | ||
- | |||
- | /** | ||
- | * Action par défaut... | ||
- | */ | ||
- | public function index(){ | ||
- | $rep = $this-> | ||
- | | ||
- | $rep-> | ||
- | | ||
- | return $rep; | ||
- | } | ||
- | |||
- | /** | ||
- | * Exemple d' | ||
- | * Récupère plusieurs enregistrements de la db | ||
- | */ | ||
- | public function browse(){ | ||
- | // CRUD | ||
- | $rep = $this-> | ||
- | |||
- | // Votre formulaire | ||
- | $rep-> | ||
- | | ||
- | return $rep; | ||
- | } | ||
- | | ||
- | /** | ||
- | * Exemple d' | ||
- | * Préparation de la saisie de nouvelles données du formulaire html | ||
- | */ | ||
- | public function create(){ | ||
- | // CRUD | ||
- | $rep = $this-> | ||
- | | ||
- | // Votre formulaire | ||
- | $rep-> | ||
- | | ||
- | return $rep; | ||
- | } | ||
- | | ||
- | /** | ||
- | * Exemple d' | ||
- | * Préparation de la modification de données du formulaire html | ||
- | */ | ||
- | public function update(){ | ||
- | // CRUD | ||
- | $rep = $this-> | ||
- | | ||
- | // Votre formulaire | ||
- | $rep-> | ||
- | | ||
- | return $rep; | ||
- | } | ||
- | | ||
- | /** | ||
- | * Exemple d' | ||
- | * Ajoute ou modifie un enregistrement dans la db | ||
- | */ | ||
- | public function save(){ | ||
- | // CRUD | ||
- | $rep = $this-> | ||
- | |||
- | // Votre formulaire | ||
- | // Les réponses "html et redirect" | ||
- | if($this-> | ||
- | $rep-> | ||
- | } | ||
- | | ||
- | return $rep; | ||
- | } | ||
- | |||
- | /** | ||
- | * Exemple d' | ||
- | * Affiche un enregistrement de la db | ||
- | */ | ||
- | public function view(){ | ||
- | // CRUD | ||
- | $rep = $this-> | ||
- | | ||
- | // Votre formulaire | ||
- | $rep-> | ||
- | | ||
- | return $rep; | ||
- | } | ||
- | | ||
- | /** | ||
- | * Exemple d' | ||
- | * Efface l' | ||
- | */ | ||
- | public function destroy(){ | ||
- | // CRUD | ||
- | $rep = $this-> | ||
- | | ||
- | 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é // | ||
- | |||
- | <code html> | ||
- | |||
- | <div id=" | ||
- | Tutoriel CRUD de base | ||
- | </ | ||
- | <div id=" | ||
- | {$MAIN} | ||
- | {$CRUDtpl} | ||
- | </ | ||
- | <div id=" | ||
- | < | ||
- | <ul> | ||
- | < | ||
- | < | ||
- | < | ||
- | </ul> | ||
- | </ | ||
- | <div id=" | ||
- | < | ||
- | </ | ||
- | |||
- | </ | ||
- | |||
- | ===== 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é // | ||
- | |||
- | |||
- | <code html> | ||
- | |||
- | < | ||
- | <br /> | ||
- | {if $rec} | ||
- | <dl> | ||
- | < | ||
- | < | ||
- | < | ||
- | < | ||
- | < | ||
- | < | ||
- | < | ||
- | < | ||
- | </dl> | ||
- | {else} | ||
- | < | ||
- | {/if} | ||
- | |||
- | </ | ||
- | |||
- | ===== Le template crudedit.tpl ===== | ||
- | Il s'agit du template du CRUD qui permet l' | ||
- | |||
- | Vous devez copier le code ci-dessous dans le fichier template nommé // | ||
- | |||
- | <code html> | ||
- | |||
- | < | ||
- | <br /> | ||
- | <form action=" | ||
- | < | ||
- | < | ||
- | < | ||
- | <input type=" | ||
- | < | ||
- | <input type=" | ||
- | < | ||
- | <input type=" | ||
- | </ | ||
- | <input type=" | ||
- | < | ||
- | </ | ||
- | |||
- | </ | ||
- | |||
- | ===== 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é // | ||
- | |||
- | <code html> | ||
- | |||
- | < | ||
- | <br /> | ||
- | {if $liste-> | ||
- | <table border=" | ||
- | {foreach $liste as $rec} | ||
- | <tr> | ||
- | < | ||
- | < | ||
- | < | ||
- | < | ||
- | <td> | ||
- | <a href=" | ||
- | <a href=" | ||
- | <a href=" | ||
- | </tr> | ||
- | {/foreach} | ||
- | </ | ||
- | {else} | ||
- | <p>Il y a aucune fiches d' | ||
- | {/if} | ||
- | |||
- | </ | ||
- | |||
- | |||
- | |||
- | ---- | ||
- | * [[tutoriels: | ||