Vous êtes sur la page 1sur 232

Guide du développeur

Jelix 1.0.6

Ed. brouillon - 17 octobre 2008


Ed. brouillon - 17 octobre 2008
Guide du développeur
ii

Copyright © 2006, 2007, 2008 Laurent Jouanneau, Les contributeurs au wiki de jelix.org

Ce manuel est distribué selon les termes de la licence Creative Commons by-nc-sa 3.0. Vous pouvez donc repro-
duire, modifier, distribuer et communiquer ce manuel au public en respectant les conditions suivantes :
– Paternité. Vous devez citer le nom de l’auteur original de la manière indiquée par l’auteur de l’oeuvre ou le
titulaire des droits qui vous confère cette autorisation (mais pas d’une manière qui suggérerait qu’ils vous sou-
tiennent ou approuvent votre utilisation de l’oeuvre).
– Pas d’Utilisation Commerciale. Vous n’avez pas le droit d’utiliser ce manuel à des fins commerciales.
– Partage des Conditions Initiales à l’Identique. Si vous modifiez, transformez ou adaptez ce manuel, vous
n’avez le droit de distribuer la création qui en résulte que sous un contrat identique à celui-ci.
Ed. brouillon - 17 octobre 2008
Guide du développeur
iii

Table des matières

I Installation 1

1 Pré-requis sur le serveur 3


1.1 Configuration de PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Configuration de PHP-Cli pour MAMP (MacIntosh) . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Configuration de PHP-Cli sous windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2 Installation de l’archive de jelix 5

3 Installation d’une application 6


3.1 Installation des fichiers de l’application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.2 Configuration du serveur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.3 Configuration pour les urls "cools" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

4 Installation sur un serveur de production 10


4.1 Choisir la bonne édition de Jelix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
4.2 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

II Fondamentaux 13

5 Principes de fonctionnement 15
5.1 Étapes d’exécution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5.2 Ce que vous avez à manipuler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
5.3 Objets en détails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
5.4 Les sélecteurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
5.5 Les objets jRequest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
5.6 Le coordinateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
5.7 Les objets jResponse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
5.8 Appeler une action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

6 Développement d’un module 21


6.1 Créer un module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
6.2 Développer un contrôleur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
6.3 Utiliser le contrôleur CRUD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
6.4 Un contrôleur pour REST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Ed. brouillon - 17 octobre 2008
Guide du développeur
iv

7 Les réponses classiques 30


7.1 Générer une page HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
7.2 Faire une redirection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
7.3 Générer du texte brut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
7.4 Générer du XML quelconque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
7.5 Générer un flux de syndication RSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
7.6 Générer un flux de syndication Atom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
7.7 Générer un PDF à partir d’un contenu LaTeX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
7.8 Générer un PDF avec TCPDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
7.9 Renvoyer un fichier binaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
7.10 Générer un fichier zip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
7.11 Générer une interface utilisateur en XUL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
7.12 Générer du RDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

8 Services web 47
8.1 AJAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
8.2 JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
8.3 JSON-RPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
8.4 XML-RPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

9 Effectuer des traitements en ligne de commande 53


9.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
9.2 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
9.3 Création d’un controller cmdline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
9.4 Création du fichier de configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
9.5 Développement d’actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
9.6 Paramètres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
9.7 Message d’aide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
9.8 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

10 Définir des traitements communs à plusieurs actions 57


10.1 Méthodes privées de contrôleurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
10.2 Héritage de contrôleurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
10.3 Personnalisation de réponse commune . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
10.4 Utilisation de zones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

III Composants de jelix 66

11 jTpl : le moteur de templates 68


11.1 L’objet jTpl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
11.2 Les fichiers templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
11.3 Les structures de contrôle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
11.4 Fonctions jTpl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
11.5 informations meta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
11.6 Informations meta avançées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
11.7 Surcharge de template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
11.8 En coulisse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Ed. brouillon - 17 octobre 2008
Guide du développeur
v

12 jZone : découper vos pages en zones 75


12.1 Principes d’une zone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
12.2 Utilisation des zones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
12.3 Appel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
12.4 Utilisation du cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
12.5 Empêcher ponctuellement la mise en cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
12.6 Paramètres automatiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

13 jDao : mapping objet relationnel 80


13.1 Fichier DAO de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
13.2 Instanciation et utilisation d’une factory et d’un record DAO . . . . . . . . . . . . . . . . . . . . . . 83
13.3 Ajouter des méthodes en XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
13.4 Développer des méthodes en php . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
13.5 Évènements automatiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

14 Formulaires classiques 95
14.1 Les actions à mettre en oeuvre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
14.2 Création d’un formulaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
14.3 Traitement des données en retour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

15 jForms : des formulaires automatiques 98


15.1 Format des fichiers jForms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
15.2 Utiliser un formulaire dans un contrôleur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
15.3 Affichage d’un formulaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
15.4 Affichage simple des données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119

16 jDb : accéder à une base de données 121


16.1 Profils et configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
16.2 Faire des requêtes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
16.3 ResultSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
16.4 Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
16.5 jDbWidget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

17 jClasses : utiliser des classes métiers 127


17.1 Création d’une classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
17.2 Instanciation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
17.3 Installer et Utiliser des classes tierces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128

18 jUrl : des URLs automatiques 129


18.1 Petit rappel sur les URLs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
18.2 Configuration générale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
18.3 Configuration des moteur d’URLs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
18.4 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
18.5 Moteur d’urls ’simple’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
18.6 Moteur d’urls significatives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
Ed. brouillon - 17 octobre 2008
Guide du développeur
vi

19 jAuth : système d’authentification 139


19.1 Mise en oeuvre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
19.2 Utiliser le contrôleur par défaut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
19.3 Utiliser son propre contrôleur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
19.4 classe jAuth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
19.5 Les drivers pour jAuth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

20 jAcl : système de droits 147


20.1 Les concepts généraux de jAcl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
20.2 Utiliser jAcl dans ses modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
20.3 Les concepts de jAcl.db . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
20.4 Configurer jAcl.db . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

21 jLocale : internationaliser votre application 159


21.1 Principes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
21.2 Fichiers properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
21.3 Récupération d’une chaîne localisée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
21.4 Chaine localisée avec paramètres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
21.5 Changer la langue dynamiquement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
21.6 Détection automatique de la langue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162

22 jEvents : communication inter-module 163


22.1 Émettre un évènement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
22.2 Répondre à un évènement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163

IV Développement avancé 165

23 Générer un contenu dans un format personnalisé 167


23.1 Créer un objet response . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

24 Système de thèmes 170


24.1 Les templates d’un thème . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
24.2 Les fichiers web d’un thème . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
24.3 Déclarer un thème par défaut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
24.4 Déclarer un thème dynamiquement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171

25 Surcharge de fichiers de modules 172

26 Développer et utiliser des plugins 173


26.1 Déclaration d’un dépôt de plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
26.2 Structure d’un dépôt et création de plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
26.3 Création de plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
26.4 plugins de coordinateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
26.5 drivers pour jAuth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
26.6 drivers pour jDb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
26.7 plugins de templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
26.8 moteurs de urls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Ed. brouillon - 17 octobre 2008
Guide du développeur
vii

27 La configuration en détails 182


27.1 Points d’entrée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
27.2 Organisation de la configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
27.3 Déscriptif des sections de la configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184

V Aide au développement 189

28 Configurer le gestionnaire d’erreur 191


28.1 Paramétrage des gestionnaires d’erreurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
28.2 Code erreur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191

29 Développer des tests unitaires 193


29.1 Développer des tests unitaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
29.2 Lancement des tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195

30 Les aides pour debogguer 197


30.1 jLog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197

VI Les classes utilitaires 198

31 jFilter : vérification et filtrage de données 200

32 jDateTime : manipulation de dates et heures 201


32.1 Initialisation à la date/heure courante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
32.2 Conversion à partir d’une chaîne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
32.3 Conversion vers une chaîne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
32.4 Calcul de dates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
32.5 Comparaison de dates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203

33 jMailer : envoi de mails 204


33.1 Classe jMailer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
33.2 Envoi d’un email basique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205

34 jWiki : transformation de texte wiki 206

35 jSession : stockage de sessions 207


35.1 Classe jSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207

VII Les plugins de Jelix 209

36 Plugins de template 211


36.1 Modificateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
36.2 Fonctions diverses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
36.3 Médias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
36.4 Meta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224

37 Plugins pour le coordinateur 225


Jelix 1.0.6
Guide du développeur
1 / 225

Première partie

Installation
Jelix 1.0.6
Guide du développeur
2 / 225

Les pages de ce chapitre expliquent en détails l’installation de Jelix puis celle d’une application y reposant dessus.
Enfin, une dernière section vous explique les points à prendre en compte pour l’installation de votre application sur
un serveur de production une fois que celle-ci est terminée.
Jelix 1.0.6
Guide du développeur
3 / 225

Chapitre 1

Pré-requis sur le serveur

Vous devez installer au minimum la version 5.2 de PHP. Les extensions dom, simplexml, pcre, session, spl et
tokenizer sont requises (elles sont actives en général dans une installation standard de PHP 5.2). Si une de ces
extensions n’était pas livrée avec le paquet PHP5, veillez à installer le paquet correspondant.
Note conçernant DOM et XML : vérifiez que c’est bien l’extension DOM et non pas l’extension DOM-XML qui
est activée dans php.ini. Certains paquets WAMP active l’extension DOM-XML en même temps que DOM, ce qui
conduit à des erreurs PHP.
Vous pouvez installer aussi un connecteur de base de données. Pour le moment Jelix prend en charge MySQL 4.1+,
PostgreSQL 8.0+, SQLite et PDO.
Si vous comptez utiliser les scripts en ligne de commande d’aide au développement (jelix-scripts), il vous faut aussi
installer la version ligne de commande de PHP : PHP-CLI.

1.1 Configuration de PHP

– magic_quotes_gpc et magic_quotes_runtime doivent être à Off. Si ce n’est pas le cas, il faut activer le plugin
magicquotes livré avec jelix.
– session.auto_start doit être à 0
– safe_mode doit être à Off (À cause des nombreux fichiers temporaires créés par jelix, il peut être difficile de
configurer une installation avec Jelix avec le safe_mode activé)
Il est également recommandé de mettre ces valeurs :
– register_globals = off
– asp_tags = off
– short_open_tag = off
Un phpinfo() peut vous permettre de vérifier votre configuration. Par défaut la configuration se trouve dans un fichier
nommé php.ini.

1.2 Configuration de PHP-Cli pour MAMP (MacIntosh)

Le logiciel MAMP met à votre disposition un programme PHP-Cli. Ce dernier n’est pas le seul PHP-Cli, en effet,
Mac OS vous en fournit aussi un en installation standard (à vérifier). Le problème vient du fait que si vous utilisez la
base de donnée MySQL de MAMP, le PHP-Cli par défaut n’est pas configuré pour vous permettre de vous connecter
à cette dernière.
Voici comment faire pour mettre le PHP-Cli de MAMP par défaut dans le terminal :
Jelix 1.0.6
Guide du développeur
4 / 225

– Ouvrez le fichier /etc/profile.


– Assurez-vous de changer les droits d’accès à ce dernier pour pouvoir le modifier.
– Ajouter à la fin du fichier les deux lignes suivantes (adaptez le chemin de MAMP si vous n’avez pas utilisé
l’installation par défaut de celui-ci) : <code>
export DYLD_LIBRARY_PATH=/Applications/MAMP/Library/lib :${DYLD_LIBRARY_PATH} export PATH=/Applicat
</code>
– Assurez-vous d’avoir laissé un saut de ligne après.
– Sauvegardez et remettez les droits d’accès à la normale.
Si vous souhaitez mettre de nouveau le PHP-Cli de base par défaut, supprimez juste les deux lignes que vous avez
ajoutées.

1.3 Configuration de PHP-Cli sous windows

– cliquer droit sur l’icône Poste de travail puis Propriétés


– dans la fenêtre Propriétés système cliquez sur l’onglet Avancé puis sur le bouton Variables d’environnement
– ensuite cliquez sur la Variable Path dans le bloc "Variables utilisateur" si vous êtes le seul utilisateur sur la machine
ou le bloc "Variables système" si il s’agit d’un serveur ou d’une machine avec plusieurs utilisateurs (afin que tous
puisse bénéficier de cette configuration).
– Dans la valeur de la variable vous ajoutez le chemin vers le répertoire qui contient PHP. Ex : D :\wamp\bin\php\php5.2.6
(n’oubliez pas d’ajouter le ; à la fin si vous avez plusieurs variables path)
– Validez en cliquant sur OK
– Fermez le tout et redémarrez.
Avec cette manipulation, vous pourrez executer PHP depuis n’importe quel répertoire notamment pour pouvoir créer
des applications en ligne de commande avec Jelix.
Jelix 1.0.6
Guide du développeur
5 / 225

Chapitre 2

Installation de l’archive de jelix

Jelix est fourni sous forme d’une archive tar.gz ou zip. Cette archive contient un répertoire jelix/lib qui contient tous
les fichiers du framework et les bibliothèques dépendantes, ainsi qu’un répertoire jelix/temp.
Décompressez l’archive avec des logiciels comme winzip, unzip ou tar.

tar xvzf jelix-1.0-dev.tar.gz

Vous obtenez les répertoires suivants :

jelix/
lib/ sources de Jelix et bibliothèques tierces
jelix/ sources de Jelix
jelix-modules/ modules livrés en standard avec Jelix
jelix-plugins/ plugins livrés en standard avec Jelix
jelix-scripts/ scripts en ligne de commande d’aide pour le développeur
jelix-www/ ressources javascript, css, xul... (1.0alpha3)
temp/ fichiers temporaires des applications jelix.

Il y a aussi d’autres répertoires dans jelix/lib/ (non listés ici), qui sont des bibliothèques additionnelles externes au
projet Jelix, et utilisées par Jelix. Il y a par exemple wikirenderer, JSON, difflib etc.
Il est recommandé d’installer ces répertoires en dehors du répertoire de votre site web, pour deux raisons :
1. plus de sécurité
2. permettre de partager une même distribution de Jelix avec plusieurs applications.
Mais ce n’est pas une obligation. Nous admettrons par la suite que vous avez copié ces répertoires dans un répertoire
monsite/.
Vous devez mettre les droits en écriture à l’utilisateur apache (ou tout autre nom d’utilisateur, celui en général qui
sert à lancer le serveur web) sur le répertoire temp.
Vous pouvez maintenant créer ou installer une application.
Jelix 1.0.6
Guide du développeur
6 / 225

Chapitre 3

Installation d’une application

Nous allons prendre l’installation de testapp en exemple mais les explications sont valables pour n’importe quelle
application.
Testapp est disponible en téléchargement. C’est une application testant divers composants de Jelix. Elle sert princi-
palement aux développeurs de Jelix, mais vous pouvez l’installer pour voir des exemples d’utilisation.

3.1 Installation des fichiers de l’application

3.1.1 Décompression de l’archive

Quand vous décompressez l’archive de testapp, vous obtenez les répertoires suivants :

testapp/ répertoire de l’application


modules/ modules de l’application
plugins/ plugins de l’application
responses/ les réponses personnalisées
var/ répertoire qui contient tout les fichiers créés ou susceptibles
config/ fichiers de configuration de l’application
log/ fichiers journaux de l’application et de Jelix
www/ racine du site de l’application (document root)

Copiez ce répertoire dans le repertoire monsite/. Vous avez donc :

monsite/
lib/
temp/
testapp/

Par défaut, l’arborescence des sources est organisée de façon à installer l’application sur un serveur sur lequel vous
pouvez spécifier le répertoire racine public du site (document root). Ce répertoire est monsite/testapp/www .
Vous pourrez bien entendu modifier l’emplacement de ces répertoires si par exemple vous ne pouvez pas modifier le
document root. Nous allons voir comment faire plus loin.
Vous remarquerez que les fichiers propres à l’application et ceux du framework sont séparés. Vous pouvez ainsi
partager le répertoire lib avec plusieurs applications.
Jelix 1.0.6
Guide du développeur
7 / 225

3.1.2 Renommer les fichiers de configuration

Dans testapp/var/config vous avez des fichiers *.dist. Renommez-les en enlevant cette particule ’.dist’.

3.1.3 Créer le répertoire temporaire

Dans monsite/temp vous devez créer le dossier testapp

3.1.4 Droits sur les répertoires

Vous devez donner le droit en écriture à l’utilisateur exécutant votre serveur web (apache ou autre) sur les répertoires
suivants :

temp/testapp/
testapp/var/config/
testapp/var/log/

3.2 Configuration du serveur

Voici ce qu’il faut configurer au niveau du serveur.

3.2.1 Si vous pouvez spécifier le document root

Si vous pouvez spécifier la racine du site en modifiant les fichiers de configuration du serveur web ou via une interface
d’administration comme le proposent certains hébergeurs, indiquez alors le répertoire monsite/testapp/www comme
étant la racine du site. Par exemple, avec apache, vous indiquerez dans le fichier httpd.conf, quelque chose comme :
<VirtualHost *>
ServerName www.monsite.com
DocumentRoot /var/monsite/testapp/www/
</VirtualHost>

Vous devez indiquer aussi un alias vers le répertoire lib/jelix-www, en le nommant jelix :
<VirtualHost *>
ServerName www.monsite.com
DocumentRoot /var/monsite/testapp/www/
Alias /jelix/ "/var/monsite/lib/jelix-www/"
</VirtualHost>

<Directory "/var/monsite/lib/jelix-www/">
AllowOverride None
Order allow,deny
Allow from all
</Directory>

Note : vous pouvez indiquer un autre nom que "jelix" pour l’alias. Vous devez alors l’indiquer dans l’option "je-
lixWWWPath" dans le fichier de configuration de l’application, monsite/testapp/var/config/defaultconfig.ini.php sec-
tion urlengine.
Et enfin dans ce même fichier vous ajusterez l’option basePath, en indiquant le chemin jusqu’au index.php (ici donc,
/) :
Jelix 1.0.6
Guide du développeur
8 / 225

basePath="/"

Ainsi, en tapant http :www.monsite.com vous accédez à votre site, et http :www.monsite.com/jelix/, à jelix-www, qui
contient un certain nombre de scripts javascript utiles, des ressources XUL etc..

3.2.2 Si vous ne pouvez pas spécifier le document root

Dans ce cas, il est préférable de déplacer le contenu du répertoire monsite/testapp/www à la racine de votre site, mon-
site/. Vous déplacerez donc les fichiers index.php, jsonrpc.php etc, pour obtenir par exemple l’arborescence suivante :

monsite/
testapp/
lib/
temp/
index.php
jsonrpc.php
xmlrpc.php

Il faut aussi modifier ces trois fichiers PHP pour changer les chemins relatifs qu’ils contiennent, et faire de même
pour le fichier testapp/application.init.php. Par exemple le fichier index.php ressemblera à ceci dans notre exemple :
require_once (’lib/jelix/init.php’);
require_once (’testapp/application.init.php’);

require_once (JELIX_LIB_CORE_PATH.’request/jClassicRequest.class.php’);
$config_file = ’config.classic.ini.php’;
$jelix = new jCoordinator($config_file);
$jelix->process(new jClassicRequest());

Il faut ensuite déplacer le répertoire lib/jelix-www/ à la racine et le renommer en "jelix". Vous obtiendrez :

monsite/
testapp/
jelix/
lib/
temp/
index.php
jsonrpc.php
xmlrpc.php

Note : vous pouvez indiquer un autre nom que "jelix" pour ce renommage. Vous devez alors l’indiquer dans l’option
"jelixWWWPath" dans le fichier de configuration de l’application, monsite/testapp/var/config/defaultconfig.ini.php
section urlengine.
Dans le fichier testapp/application.ini.php, vous devez modifier la constante JELIX_APP_WWW_PATH :
define (’JELIX_APP_WWW_PATH’, realpath(JELIX_APP_PATH.’../’).’/’);

Et enfin, dans le fichier monsite/testapp/var/config/defaultconfig.ini.php, vous ajusterez l’option basePath, en indi-


quant le chemin jusqu’au index.php (ici donc, /) :
basePath="/"

Vous pouvez alors taper l’adresse de votre site (http :www.monsite.com par exemple, ou http :localhost/)
Jelix 1.0.6
Guide du développeur
9 / 225

3.2.3 Spécifier une extension de fichier autre que .php

Sur certains serveurs, il vous est proposé PHP4 et PHP5 à la fois. En général, les fichiers .php doivent être des
fichiers PHP4, et .php5, des fichiers PHP5. Il vous faut donc faire des modifications pour que votre application jelix
fonctionne avec PHP5. Deux façons, selon les possibilités.

Par le .htaccess

Dans le répertoire www de votre application rajoutez un fichier .htaccess et mettez y :

AddHandler php5-script .php

Et vous n’avez rien d’autre à faire. Si ça ne fonctionne pas, faites comme suit.

En renommant l’extension

Il faut renommer le fichier index.php en index.php5 (idem pour les autres fichiers php se trouvant dans www :
jsonrpc.php, xmlrpc.php, etc...). Par contre, vous n’avez pas besoin de renommer les fichiers php des autres réper-
toires !
Dans le fichier de configuration var/config/defaultconfig.ini.php, indiquez l’extension dans la partie urlengine :

entrypointExtension = .php5

3.3 Configuration pour les urls "cools"

Pour pouvoir utiliser des urls significatives avec le système d’url automatique de jelix, il faut activer dans apache (au
niveau de la configuration serveur ou dans le .htaccess si cela est permis) :

Options +Multiviews

Et pour Apache 2, rajouter :

AcceptPathInfo on

Pour vérifier que cela fonctionne, créez sur votre site web un fichier test.php qui affiche phpinfo() et essayez l’url :
monsite.com/test/foo/bar . Le phpinfo devrait s’afficher, et vous devriez avoir dans $_SERVER[’PATH_INFO’] la
chaine "/foo/bar" (voir tout en bas de l’affichage de phpinfo).
Jelix 1.0.6
Guide du développeur
10 / 225

Chapitre 4

Installation sur un serveur de production

On appelle serveur de production, le serveur sur lequel sera installé votre application une fois terminée, donc acces-
sible aux utilisateurs finaux. Par opposition, il y a le serveur de développement, celui sur lequel vous développez votre
application.
Il y a certaines choses différentes à prendre compte dans le cas du serveur de production, afin d’optimiser l’exécution
de votre application basée sur Jelix.

4.1 Choisir la bonne édition de Jelix

Pour développer, vous utilisez bien sûr l’édition "developer" de Jelix. Cette édition comprend les outils de scripts
en ligne de commande et d’autres choses pour le développement.
Cependant, pour l’installation sur un serveur de production, il est préférable d’installer l’édition "optimized" de
Jelix. Comme son nom l’indique, elle est optimisée, et débarrassée des choses inutiles en production. Notez toutefois
que votre application fonctionnera à l’identique avec l’une ou l’autre des éditions de Jelix, à un détails près : on pourra
observer de légères améliorations de performance avec l’édition "Optimized" ;-).
Si vous choisissez de rester avec l’édition "developer" sur le serveur de production, il n’y a pas de problème à cela.
Il est toutefois recommandé de supprimer les scripts en ligne de commande de Jelix.
Note : une édition "Gold" expérimentale est disponible en téléchargement, pour les développeurs qui peuvent
modifier la configuration de php, en particulier, installer des extensions PHP. En effet, cette édition repose sur certaines
extensions PHP qui ne sont pas disponibles chez tous les hébergeurs, mais aussi sur une extension PHP spécialement
dédiée à Jelix, qui prend en charge certains traitements du framework. L’utilisation de l’édition GOLD améliore ainsi
sensiblement les performances de votre application.

4.2 Configuration

L’installation se passe à l’identique que sur le serveur de développement, y compris pour l’application.
Pour avoir de meilleur performance et plus de sécurité, voici toutefois quelques conseils supplémentaires.

4.2.1 Au niveau du serveur

1. Tous les répertoires autre que le www de votre application devraient être en dehors du "document root" du site
web.
Jelix 1.0.6
Guide du développeur
11 / 225

2. Bien spécifier les droits sur le répertoire temp, en particulier, que le propriétaire soit l’utilisateur qui exécute
apache (ou celui de votre compte, chez certains hébergeurs) et qu’il ait les droits en écriture. Par exemple, sur
linux, il n’est pas recommandé de mettre les droits 0777 sur le répertoire temp ;-)

4.2.2 Au niveau de l’application

Voici quelques conseils au niveau de la configuration de l’application, donc les modifications à faire au niveau du
fichier var/config/defaultconfig.ini.php .

section error_handling

Dans la section error_handling, la configuration suivante est vivement conseillée :


[error_handling]
messageLogFormat = "%date%\t[%code%]\t%msg%\t%file%\t%line%\n"
logFile = error.log
email = root@localhost
emailHeaders = "From: webmaster@yoursite.com\nX-Mailer: Jelix\nX-Priority: 1 ( ←-
Highest)\n"
quietMessage="A technical error has occured. Sorry for this trouble."

; mots clés que vous pouvez utiliser : ECHO, ECHOQUIET, EXIT, LOGFILE, SYSLOG, ←-
MAIL, TRACE
default = ECHOQUIET EXIT LOGFILE
error = ECHOQUIET EXIT LOGFILE
warning = ECHOQUIET LOGFILE
notice =
strict =
; pour les exceptions, il y a implicitement un EXIT
exception = ECHOQUIET LOGFILE

En clair, il est déconseillé d’utiliser le mot clé ECHO, qui affiche tous les détails des erreurs dans les pages web (in-
formations qui pourraient être utiles pour des pirates), mais plutôt ECHOQUIET, qui affiche simplement le message
indiqué dans le paramètre quietMessage.
Toutefois, il est utile d’être informé des erreurs et de leurs détails. Aussi, parallèlement à ECHOQUIET, il est
recommandé d’ajouter l’un de ces mots clés
– LOGFILE : les erreurs sont insérées dans le fichier indiqué dans logFile
– SYSLOG : les erreurs sont enregistrées au niveau du système
– MAIL : les erreurs sont envoyées par Mail.
Attention à l’usage de MAIL : ne l’utiliser qu’une fois que vous savez que votre application fonctionne bien sur le
serveur de production. Sinon vous risquez d’être inondé de mails (voire même que votre hébergeur n’appréciasse pas
l’usage intensif du mail, pouvant vous prendre pour un spammeur).
Attention aussi à l’usage de SYSLOG : ne mettre cette option que si il s’agit de votre serveur (c’est à dire que vous
êtes administrateur de la machine). Sinon le propriétaire de la machine risque de ne pas apprécier.
En conclusion : LOGFILE est plutôt conseillé par rapport à MAIL et à SYSLOG ;-)

Section compilation

Dans la section compilation, vous pouvez désactiver l’option checkCacheFiletime, et encore plus recommandé,
l’option force si vous l’avez activé pour le développement.
Jelix 1.0.6
Guide du développeur
12 / 225

[compilation]
checkCacheFiletime = off
force = off

L’option checkCacheFiletime évite à Jelix de vérifier tout le temps que le cache (les fichiers générés par Jelix pour
les fichiers de configurations, les DAO, templates etc) est bien à jour par rapport aux fichiers de l’application. À
priori, cette vérification est inutile en production, puisque l’application est rarement modifiée. Bien sûr, si vous la
désactivez, il faudra impérativement vider le répertoire de cache (temp/votre_appli/) à chaque mise à jour de votre
application , pour que vos modifications soient bien prises en compte ! (surtout quand il s’agit de modification dans
la configuration, des daos, locales, templates..)

Section mailer

N’oubliez pas de mettre à jour les paramètres de la section mailer. En effet, les paramètres pour envoyer des mails
ne sont pas toujours identiques entre le serveur de développement et le serveur de production.
Jelix 1.0.6
Guide du développeur
13 / 225

Deuxième partie

Fondamentaux
Jelix 1.0.6
Guide du développeur
14 / 225

Comme tout framework, Jelix a des principes de fonctionnement et une série d’objets à connaître, en particulier ceux
qui sont utilisés dans la logique MVC : Modèle, Vue, Controlleur.
Vous allez apprendre dans cette partie à créer un module et à utiliser les contrôleurs et les réponses.
Jelix 1.0.6
Guide du développeur
15 / 225

Chapitre 5

Principes de fonctionnement

Voici quelques explications sur le fonctionnement du framework et sur les principaux objets que vous allez avoir à
utiliser.
Le framework se base sur un principe : à chaque URL correspond une action.

5.1 Étapes d’exécution


Jelix 1.0.6
Guide du développeur
16 / 225

1. Le serveur web reçoit une requête HTTP.


– Le point d’entrée est exécuté par le serveur lorsqu’une URL l’indique. Par défaut il s’agit de index.php.
– Ce script instancie un objet de type jRequest et un coordinateur de type jCoordinator.
– L’objet jRequest analyse alors le contenu de la requête HTTP pour en extraire les données. Celles-ci peuvent
être dans l’URL et/ou dans le corps de la requête (méthode POST par exemple).
– En particulier jRequest détermine le nom de l’action à exécuter et le nom du module concerné.
2. Le paramètre action contient le nom du contrôleur et la méthode à exécuter. Ce contrôleur est donc instancié et
la méthode exécutée. La méthode récupère les paramètres de requête pour déterminer les traitements à suivre.
3. Le contrôleur exécute les traitements métiers et récupère éventuellement des résultats qui seront utilisés pour
l’affichage.
4. Le contrôleur instancie un objet de type jResponse auquel il assignera les données à afficher, initialisera les
templates, etc...
5. Jelix récupère cet objet jResponse, invoque la génération du document en sortie et envoi ce dernier au navigateur.

5.2 Ce que vous avez à manipuler

En général, vous n’aurez pas à utiliser un objet jRequest ou jCoordinator.


Vous aurez par contre à créer un objet de type jController pour y inclure le code d’une action. Cet objet propose des
méthodes pour récupérer les paramètres extraits par jRequest, mais aussi pour récupérer un objet jResponse. Vous
aurez donc dans le code de l’action, en plus de manipuler vos objets "métier", à manipuler cet objet jResponse pour
indiquer les données à renvoyer au navigateur.

5.3 Objets en détails

Voyons maintenant un descriptif de chaque objet présenté ici ainsi que d’autres, à commencer par les sélecteurs.

5.4 Les sélecteurs

5.4.1 L’utilité des sélecteurs

Les sélecteurs sont très utilisés dans Jelix. Ils permettent d’indiquer une ressource, un fichier, sans avoir à connaître
son chemin. En effet, l’arborescence d’une application Jelix n’est pas figée et peut être modifiée selon les normes en
vigueurs sur le serveur (le répertoire var de l’application myapp allant dans le répertoire /var/myapp/var par exemple,
sur un serveur unix).
De plus les bibliothèques de Jelix peuvent être installées dans une arborescence différente de celle de l’application.
Aussi les sélecteurs permettent de ne pas avoir à modifier son application quand elle est installée différemment.
Et ils permettent aussi d’éviter à devoir taper de long chemins de fichiers...

5.4.2 Comment est défini un sélecteur

Un sélecteur est une chaîne ayant ce format : "unModule~uneRessource" . On peut omettre le module si on se trouve
actuellement dans le module en question. Dans ce cas on écrit "uneRessource".
Un sélecteur désigne une ressource d’un type précis. Voici donc les différents types de sélecteurs :
Jelix 1.0.6
Guide du développeur
17 / 225

En règle générale, vous aurez à donner un sélecteur en paramètre de certaines méthodes sans avoir à indiquer son
type. Très souvent en effet ces méthodes savent qu’il s’agira d’un sélecteur sur une ressource d’un type précis.

jDao::create("myModule~myDao");

Ici jDao cherchera un fichier DAO de nom myDAO.dao.xml dans le module myModule.

5.4.3 Définir un sélecteur d’un type précis

Il peut arriver (mais c’est en fait très rare dans l’API de Jelix) que la méthode attende n’importe quel type de sélecteur.
Dans ce cas là il faut ajouter un préfixe au sélecteur de manière à indiquer son type. Ce préfixe est indiqué dans le
tableau du dessus. La notation d’un sélecteur est alors :

"type:unModule~uneRessource"

On appelle cela un "sélecteur complet".


On utilisera alors l’objet jSelectorFactory pour récupérer l’objet sélecteur correspondant (voir la colonne classe dans
le tableau) et donc le chemin physique de la ressource indiquée.
$unSelecteur = "tpl:foo~bar";
...
$selector = jSelectorFactory::create($unSelecteur); // $selector sera un objet ←-
de type jSelectorTpl
$chemin_du_template = $selector->getPath();

5.5 Les objets jRequest

5.5.1 Un objet jRequest pour chaque type de requête

Un objet jRequest prend en charge le traitement des données en entrée afin de les rendre disponibles facilement au
framework et plus spécifiquement aux actions. Il permet entre autre de déterminer le module et l’action à exécuter.
Il y a plusieurs types d’objets jRequest qui permettent de traiter différentes données en entrée. En effet, on ne récupère
pas les données en entrée pour une page HTML (situées dans l’URL pour une requête GET ou URL-encodées dans
son corps pour une requête POST) de la même manière que celles d’un appel XML-RPC (les données étant situées
dans le corps de la requête HTTP sous forme XML).
À chaque type d’objet jRequest correspond un ou plusieurs formats de sortie autorisés, donc un ou plusieurs objets
jResponse permis.
Les objets jRequest disponibles sont :
– classic : pour les requêtes classiques dont le type de réponse est indifférent (HTML, texte, redirection...),
– xmlrpc : pour les requêtes XML-RPC. La réponse sera nécessairement en XML-RPC,
– jsonrpc : pour les requêtes JSON-RPC. La réponse sera nécessairement en JSON-RPC.
D’autres sont possibles (SOAP par exemple).
Jelix 1.0.6
Guide du développeur
18 / 225

5.5.2 Point d’entrée

Il faut un fichier d’entrée PHP pour chaque type de requête que l’on veut utiliser. Pour le classique (a priori, in-
dex.php), ça ressemble à ça :
// inclusion du fichier principal de jelix
require_once (’../../lib/jelix/init.php’);

// inclusion du fichier principal de l’application


require_once (’../../myapp/application.init.php’);

// inclusion d’un objet jRequest de son choix


require_once (JELIX_LIB_CORE_PATH.’request/jClassicRequest.class.php’);

// on indique le fichier de configuration correspondant au point d’entrée


// ici le fichier de config est dans var/config/index/
$config_file = ’index/config.ini.php’;

// instanciation du coordinateur et lancement du processus


$jelix = new jCoordinator($config_file);
$jelix->process(new jClassicRequest());

5.5.3 API

Durant l’exécution de l’action, l’objet jRequest correspondant à la requête est accessible via la propriété request
du coordinateur. Ce dernier est accessible via une variable globale $gJCoord.
// pour récupérer un paramètre en dehors d’un contrôleur
$myfooValue = $GLOBALS[’gJCoord’]->request->getParam(’foo’);

Mais dans un contrôleur, vous avez à votre disposition des méthodes "raccourcis" :
$myfooValue = $this->param(’foo’);

Les autres propriétés de request qui peuvent être utiles :

5.6 Le coordinateur

Le coordinateur est le coeur du framework. C’est en quelque sorte le chef d’orchestre de l’exécution d’une action.
À partir des paramètres donnés par un objet jRequest, le coordinateur en déduit les informations suivantes :
– le nom du module et le nom de l’action à exécuter
– les données en entrée
– la liste des types de réponses possibles et le type de la réponse par défaut
Des plugins peuvent modifier éventuellement ces informations (ex : plugin qui vérifie l’authentification et redirige
alors vers une autre action, ...).
Avec ces informations il va donc récupérer le contrôleur correspondant et exécuter la méthode qui implémente le
traitement correspondant à l’action.
Il récupérera l’objet jResponse fourni par le traitement de l’action pour alors renvoyer au navigateur le contenu
généré par jResponse.
Jelix 1.0.6
Guide du développeur
19 / 225

5.7 Les objets jResponse

5.7.1 jResponse

Un objet jResponse représente la vue dans le modèle MVC. Il est chargé de contrôler et de générer correctement la
réponse, c’est à dire les données en sortie. Toute demande d’"affichage" passe par cet objet.
Il existe plusieurs objets qui hérite de la classe jResponse, chacun prenant en charge un format spécifique en sortie :
html, texte, fichiers binaires, pdf, XML-RPC etc... Mais aussi des réponses particulières comme la redirection.
Un objet jResponse implémente un certain nombre de méthodes, dont les plus utiles pour vous sont celles-ci :
– addHttpHeader () : pour ajouter un entête HTTP, qui sera envoyé au moment opportun.
– setHttpStatus () : pour indiquer le code "status" HTTP (200, 404...)
Ces méthodes sont disponibles pour tout type de réponse.
Pour connaître les spécificités des différents objets réponses, voir le chapitre sur les réponses.

5.8 Appeler une action

5.8.1 Appeler une action

Une fois que l’on a fait un contrôleur on veut bien sûr pouvoir appeler l’une de ces méthodes, donc indiquer les
informations nécessaires dans les URLs.
Avec la configuration par défaut de Jelix (donc avec le moteur d’URL simple), il faut indiquer dans l’URL :
– le nom du module
– le nom de l’action constituée du nom du controleur et du nom de la méthode
On le fait en indiquant les paramètres module et action.
index.php?module=monmodule&action=moncontroleur:mamethode

Notez que le nom du contrôleur et de la méthode doivent être séparés par le caractère " :".
– Si le paramètre action n’est pas présent, Jelix essaiera d’exécuter la méthode index du contrôleur default.
– Si le paramètre module est absent, Jelix essaiera d’exécuter l’action indiquée du module indiqué dans le paramètre
startModule dans la configuration de l’application.
– Si les deux paramètres sont absents, Jelix exécutera l’action indiquée dans le paramètre startAction, à partir du
module indiqué dans le paramètre startModule dans la configuration de l’application.
– Dans le paramètre action, si on indique juste le nom de la méthode, Jelix exécutera la méthode indiquée dans le
contrôleur default

5.8.2 Sélecteurs d’action

Dans vos templates et dans votre code en général, vous n’indiquerez jamais d’URL "en dur". Jelix comporte des
mécanismes (la classe jUrl notament) pour générer les URLs correspondantes à des actions. Ceci permet de choisir
son moteur d’URL préféré (simple ou significant) et de modifier le "mapping" entre des URLs significatives et des
actions. Tout ceci sans toucher ni aux templates, ni aux contrôleurs.
Aussi vous allez devoir la plupart du temps indiquer à divers objets ou méthodes de l’API de Jelix des sélecteurs
d’action accompagnés d’éventuels paramètres. Voir la page sur les sélecteurs pour en savoir plus sur les sélecteurs en
général.
Les sélecteurs d’action ont cette syntaxe :
Jelix 1.0.6
Guide du développeur
20 / 225

module~controleur:methode

Vous pouvez omettre l’une de ces parties comme spécifié précédemment :


controleur:methode
methode
module~
controleur:

Vous pouvez aussi indiquer le caractère "#" pour spécifier le module courant ou l’action courante. Dans ces exemples,
imaginons que c’est l’action "bar :man" du module "foo" qui a été appelée dans Jelix :
– "#~controleur :methode" représente l’action "controleur :methode" du module qui a été appelé. Équivaut donc à
"foo~controleur :methode"
– "module~#" représente l’action qui a été appelée mais du module indiqué. Équivaut donc à "module~bar :man"
– "#~#" représente le module/l’action qui ont été appelés. Équivaut donc à "foo~bar :man".

5.8.3 Indiquer le point d’entrée

Par défaut quand on indique un sélecteur d’action, il génère l’URL avec le point d’entrée courant : si on a appelé
Jelix avec index.php, ce sera index.php, si c’est xmlrpc.php, ce sera xmlrpc.php.
Cependant on peut vouloir indiquer des URLs pour d’autres points d’entrées. Par exemple, on est dans une action
qui affiche une page html et on veut indiquer dans la page l’URL du point d’entrée pour les services web jsonrpc.
Dans ce cas on ajoute à la fin du sélecteur d’action, un "@" suivi du nom du type du point d’entrée :
foo~bar:man@css

Ici on demande l’URL de l’action "bar :man" du module "foo", pour les requêtes de type "css".
Pour la plupart des URLs on indiquera certainement "@classic".
Si dans un sélecteur d’action on n’indique juste le type de requête, seront utilisés le module et l’action indiqués
respectivement dans startModule et startAction de la configuration de l’application. Ainsi par exemple le sélecteur
"@classic" correspondra à l’URL "index.php".
Pour en savoir plus : configuration et la manipulation des URLs dans Jelix.
Jelix 1.0.6
Guide du développeur
21 / 225

Chapitre 6

Développement d’un module

Les contrôleurs et fonctionnalités de votre application doivent être regroupés en modules.


Un module contient un ensemble de fichiers, entre autre :
– Des contrôleurs
– Des classes métiers
– Des templates
– Des fichiers daos
– Des formulaires
– Des fichiers de langues
Les fichiers d’un module sont censés concerner un même domaine fonctionnel. Par exemple, un module "news"
contiendra tous les fichiers qu’il faut pour afficher et/ou gérer les news.
Dans une application, vous devez avoir au moins un module qu’il vous faut créer. Ce sera en général ce qu’on appelle
le module principal, qui pourrait contenir par exemple ce qu’il faut pour afficher la page d’accueil de votre site.
Notez qu’il y a implicitement un autre module déclaré automatiquement dans votre application : le module "jelix",
situé dans lib/jelix/core-modules/jelix.
Dans la suite, nous allons voir comment créer un module et un contrôleur.

6.1 Créer un module

6.1.1 Déclarer les répertoires de modules

Un module est un répertoire dans lequel il y a une arborescence précise. Les modules sont regroupés dans un ou
plusieurs répertoires que l’on appelle groupe de modules, ou aussi dépôt de modules.

Configuration générale

Pour avoir accès aux modules, il faut déclarer ces dépôts de modules dans la configuration, par la propriété modu-
lesPath. On peut y indiquer plusieurs chemins en les séparant par des virgules. On peut indiquer soit des chemins
complets, soit des chemins relatifs à un répertoire spécifique de l’arborescence Jelix. Ces chemins relatifs ont une
notation spéciale :

coderepertoire:chemin/relatif/
Jelix 1.0.6
Guide du développeur
22 / 225

coderepertoire est un de ces codes :


Cela évite d’avoir à indiquer un véritable chemin relatif. Et donc d’avoir à changer à la fois le fichier applica-
tion.init.php et le fichier de configuration quand on fait une modification dans l’arborescence, quand on migre l’appli-
cation d’un serveur à un autre (entre le développement et la production par exemple).
Exemple :
modulesPath = lib:jelix-modules/,app:modules/

On déclare ici qu’il y a deux dépôts de modules : le premier, jelix-modules, se trouvant dans le répertoire lib de jelix ;
le deuxième, le répertoire modules de l’application.
Tous les modules se trouvant dans ces deux répertoires seront utilisables et les actions qu’ils déclarent pourront être
appelées depuis un navigateur.

Restrictions

Il se peut que parmi les modules présents dans un dépôt, on veuille en désactiver certains : cela peut arriver si ce
groupe de module est partagé par plusieurs applications et que pour l’application courante, on ne veuille pas utiliser
certains de ces modules. Ou encore que pour plus de sécurité, on interdisent l’accès à certains modules pour certains
points d’entrée.
On dispose alors de deux paramètres de configuration :
checkTrustedModules = on
trustedModules = foo,bar,baz

On active la restriction d’accès via le paramètre checkTrustedModules, et on indique les modules autorisés dans
trustedModules. Les autres modules ne seront pas accessibles de l’extérieur. Par contre, les modules autorisés peuvent
accéder aux ressources des modules non autorisés (classes, zones, dao...).

6.1.2 Créer un module

Le principe : il suffit de créer un répertoire dans un dépôt, avec un nom précis, et d’y mettre les contrôleurs, les daos
et tout ce qu’il faut dans leurs sous-répertoires respectifs.
Le plus simple est encore d’utiliser le script jelix et la commande createmodule :
php jelix.php createmodule monmodule

Cela vous créé un module de nom "monmodule" dans le répertoire modules/ de l’application, des sous répertoires
ainsi qu’un contrôleur par défaut.

6.2 Développer un contrôleur

Les contrôleurs sont les objets qui vont effectuer les actions correspondantes à chacune des urls de votre application.
Un contrôleur possède une ou plusieurs méthodes correspondant à des actions, qui vont effectuer des traitements et
préparer une réponse (html, redirection, ...) pour le navigateur.
Un contrôleur est toujours dédié à un type de requête particulier.
Jelix 1.0.6
Guide du développeur
23 / 225

6.2.1 Convention de nommage

Fichier

Les contrôleurs doivent être stockés dans le répertoire controllers des modules. Ils ont chacun un nom qui va servir
de suffixe ou préfixe.
Le fichier d’un contrôleur a un nom bien précis :

cccc.tttt.php


– cccc est le nom du contrôleur
– tttt est le type de requête auquel il est dédié.
Par exemple, si vous l’appelez "foo", et qu’il est dédié au type de requête "classic" (ce qui sera le plus souvent le
cas), le nom du fichier sera foo.classic.php.

Classe

La classe d’un contrôleur doit toujours avoir le suffixe "Ctrl". Dans le cas d’un contrôleur nommé "foo", sa classe
devra être nommée "fooCtrl".

6.2.2 Création d’un contrôleur

Chaque module a en principe un contrôleur principal, que l’on appelle généralement "default". On va prendre ce nom
pour l’exemple de création de contrôleur.
En suivant les conventions de nommage, on créé donc une classe de nom "defaultCtrl" dans un fichier controllers/-
default.classic.php.
Voici le code source minimal :

class defaultCtrl extends jController {

Une classe de contrôleur doit toujours hériter de la classe jController.


Ensuite, il faut ajouter au moins autant de méthodes que d’actions prises en charge par le contrôleur. Ces méthodes
sont publiques, n’ont pas d’arguments, et doivent renvoyer un objet de type jResponse.
Voici un exemple de méthode pour une action "index" :

class defaultCtrl extends jController {

public function index(){


$rep = $this->getResponse(’html’);
$rep->addContent(’<p>Test</p>’);
return $rep;
}

}
Jelix 1.0.6
Guide du développeur
24 / 225

Note : quand le nom d’une action est absent, ou incomplet (il n’y a que le nom de la méthode ou que le nom du
contrôleur), alors Jelix complètera le nom de l’action avec "default" pour le contrôleur et "index" pour le nom de la
méthode. Il est donc recommandé d’avoir toujours un contrôleur "default" dans un module et une méthode "index"
dans chaque contrôleur.

Utilisation d’un constructeur de classe

Pour utiliser un constructeur de classe dans un contrôleur, il est nécessaire de mentionner le constructeur parent ainsi
que d’y lier l’argument $request. Exemple :

class defaultCtrl extends jController {


function __construct($request) {
parent::__construct($request);
/* Reste du code du contrôleur ici */
}
}

6.2.3 Services fournis par jController

Dans une action, vous avez un certains nombre de méthodes à votre disposition.

Récupérer un objet jResponse

Vous devez toujours renvoyer un objet dérivant de jResponse, qui est en fait le "view" du modèle MVC. Il y a un
certains nombres d’objet jResponse fournies par Jelix, permettant de générer du XHTML, du JSON, du text, du css,
du xml, du zip ou même faire des redirections. Chaque type d’objet jResponse est déclaré dans jelix par un mot clé.
Aussi, pour récupérer un objet "réponse" précis, vous appelez la méthode getResponse en indiquant le mot clé
correspondant au type de réponse que vous voulez.
$rep = $this->getResponse(’html’);

$rep contient ici une réponse qui va générer du html. l’objet $rep est du type jResponseHtml.
Sachez que vous pouvez définir vos propres types de réponses, voir même plusieurs type de réponse issue d’un même
type, afin d’avoir d’éviter de dupliquer du code, ou de prendre en charge un format que ne connait pas jelix. Voyez
pour cela l’article sur la création des réponses personnalisées.

Récupérer les paramètres de requête

Comme vous le savez, les paramètres de la requête http sont stockés dans un objet jRequest, qui lui même est stocké
dans l’objet jCoordinator. On peut ainsi récupérer un paramètre de cette façon :
$id = $GLOBALS[’gJCoord’]->request->getParam(’id’);

Mais il y a plus pratique : la méthode param() disponible dans les contrôleurs, au résultat équivalent.
$id = $this->param(’id’);

Si il n’y a pas de paramètre de nom id, le résultat sera la valeur null. Vous pouvez aussi indiquer en deuxième
argument une valeur qui sera prise si le paramètre indiqué n’existe pas.
Jelix 1.0.6
Guide du développeur
25 / 225

$titre = $this->param(’title’,’un titre’);

Il y a d’autres méthodes similaires, comme intParam(), floatParam() et boolParam(), prenant les mêmes argu-
ments, mais transformant le paramètre récupéré dans le type de donnée correspondant. Avec intParam(), vous ob-
tiendrez un nombre entier ; avec floatParam(), un décimal. Cela permet ainsi de "filtrer" les données. Et pour bool-
Param(), vous obtiendrez true si le paramètre vaut "true", "1", "on" ou "yes", et false dans le cas contraire.
Si vous voulez un filtrage pour d’autres types de données, utilisez la classe jFilter.

6.3 Utiliser le contrôleur CRUD

6.3.1 Introduction

Un contrôleur (jControllerDaoCrud) est fourni avec jelix pour faire du CRUD. CRUD veut dire Create, Read, Update,
Delete. En substance, c’est un contrôleur qui contient toutes les actions pour créer, lire, mettre à jour et effacer un
enregistrement d’une table, et lister les enregistrements de cette table. Il lui faut en gros pour fonctionner, le nom d’un
fichier DAO et d’un fichier jForms. Il s’occupe du reste.
C’est donc un contrôleur permettant de mettre en place rapidement une gestion d’un enregistrement de table.

6.3.2 Création d’un CRUD

Pour l’utiliser, il faut créer un contrôleur dans votre module, qui hérite non pas de jController, mais de jController-
DaoCrud. Exemple, dans un fichier samplecrud.classic.php
class sampleCrudCtrl extends jControllerDaoCrud {

Il faut ensuite lui indiquer un DAO qui utilise la table que l’on veut gérer, et un fichier jforms, qui permettra d’afficher
le formulaire d’édition d’un enregistrement. Cela se fait au travers des propriétés $dao et $form :
class sampleCrudCtrl extends jControllerDaoCrud {

protected $dao = ’testapp~products’;

protected $form = ’testapp~products’;

Et c’est tout ! En imaginant que ce contrôleur se trouve dans le module main, affichez alors la page

index.php?module=main&action=samplecrud:index

Vous avez alors toutes les pages qu’il faut pour gérer les enregistrements de la table.
Important : par défaut, le controleur récupère la réponse HTML définit dans jelix, c’est à dire qu’il vous faut faire
une réponse HTML personnalisée. Si vous n’en avez pas, rien ne s’affichera. Si vous ne voulez pas faire de réponse
personnalisée (ce qui est dommage), il faudra configurer le contrôleur.
Jelix 1.0.6
Guide du développeur
26 / 225

6.3.3 Personnalisation

Il se peut que le comportement par défaut du controleur et des affichages des pages ne correspondent pas à ce que
vous voulez, et qu’il faille faire des choses au niveau du formulaire (préremplir à la main des listbox par exemple).
Voici donc ce qui est possible de faire.

Indiquer le profil jDb

Si il faut utiliser un profil de connexion spécifique, indiquez le dans la propriété $dbProfil :


protected $dbProfil = ’admin’;

Configurer la réponse

Par défaut, comme il a été dit plus haut, le controleur récupère la réponse HTML par défaut. Cela se fait dans la
méthode _getResponse() du contrôleur :
protected function _getResponse(){
return $this->getResponse(’html’);
}

L’objet réponse renvoyé par cette méthode est alors utilisé par toutes les actions du contrôleur CRUD.
Comme vous le voyez, rien n’est fait au niveau de la réponse : pas de déclaration de template principal (bodyTpl),
pas de feuille de style ou autre. Le contrôleur s’attend en effet à ce que l’objet renvoyé par getResponse soit un objet
réponse crée par vos soins et communs à tous vos contrôleurs.
Si vous voulez donc changer ça, surchargez donc ces méthodes en y ajoutant ce que vous voulez. Exemple :
protected function _getResponse(){
$rep = $this->getResponse(’html’);
$rep->addCSSLink(’admin.css’);
$rep->body->assignZone(’menu’, ’adminmenu’);
return $rep;
}

Ainsi la page de liste des enregistrement, de vue et d’édition d’un enregistrement etc auront une feuille de style
admin.css et un menu qui est généré par la zone adminmenu.

Intégration des templates dans la réponse

Chaque action d’affichage du contrôleur CRUD utilise un template, dont le contenu sera assigné au template principal
de la réponse dans la variable de template MAIN. En d’autres termes, chaque action fait l’équivalent de :
$rep->body->assign(’MAIN’, $resultatTemplateAction);

Si vous voulez que ce soit dans une variable de template autre que MAIN, vous pouvez changer la propriété $tem-
plateAssign :
class sampleCrudCtrl extends jControllerDaoCrud {
//...
protected $templateAssign = ’AUTRE’;
//...
}
Jelix 1.0.6
Guide du développeur
27 / 225

6.3.4 Liste des enregistrements

Elle est affichée par l’action index.

Configuration simple

Des propriétés du contrôleur CRUD permettent de configurer l’affichage de la liste.

Nombre d’enregistrements par page

Il est défini par la propriété $listPageSize :


protected $listPageSize = 20;

Liste des propriétés

Par défaut, toutes les propriétés du DAO sont affichées. Si vous voulez restreindre, indiquez la liste des propriétés à
afficher dans propertiesForList :
protected $propertiesForList = array(’titre’,’date_creation’,’auteur’);

Ordre d’affichage

Il n’y a pas d’ordre spécifique pour afficher les enregistrements. Pour forcer un ordre précis, indiquée la liste des
propriétés du dao qui serviront d’ordre, et le sens :
protected $propertiesForRecordsOrder = array(’date’=>’desc’, ’title’=>’asc’);

Template

Le template par défaut utilisé pour lister les enregistrement est ’jelix~crud_list’.
protected $listTemplate = ’jelix~crud_list’;

Vous pouvez bien sûr soit le surcharger dans un thème, soit en indiquer un autre.
Le template recevra les variables de templates suivantes :
– list : liste des résultats (renvoyé par le dao)
– primarykey : le nom de la clé primaire
– properties : la liste des propriétés à afficher
– controls : la liste des contrôles du formulaire jforms, permettant donc d’obtenir le libellé de chaque entête de
colonne de chaque propriété.
– editAction : le nom de l’action pour le lien d’édition d’un enregistrement
– editAction : le nom de l’action pour le lien d’édition d’un enregistrement
– createAction : le nom de l’action pour le lien de création d’un enregistrement
– deleteAction : le nom de l’action pour le lien de suppression d’un enregistrement
– viewAction : le nom de l’action pour le lien de visualisation d’un enregistrement
– listAction : le nom de l’action pour le lien de la liste des enregistrements (donc l’action présente)
– listPageSize : la valeur de $listPageSize
– page : la valeur du paramètre url "offset", indiquant le numéro d’ordre du premier enregistrement à afficher dans
la liste.
– recordCount
– offsetParameterName
Jelix 1.0.6
Guide du développeur
28 / 225

6.3.5 Configuration avancée de la liste

6.3.6 Détails d’un enregistrement

6.3.7 Création d’un enregistrement

6.3.8 Mise à jour d’un enregistrement

6.3.9 Destruction d’un enregistrement

6.4 Un contrôleur pour REST

La technique REST consiste à utiliser les fonctionnalités du protocole HTTP pour manipuler une ressource. En
effet, il existe les méthodes POST et GET que vous connaissez, mais il existe aussi les méthodes PUT et DELETE.
Ainsi, pour effectuer une création, un affichage, un effacement d’une ressource, plutôt que d’avoir plusieurs URLs
spécifiques pour faire cela, il y a une seule URL, et on utilise le champ "method" de HTTP pour indiquer l’action à
effectuer.
Pour en savoir plus sur les principes de REST, il existe pas mal d’explications sur le web. N’hésitez pas à googler !
Voyons maintenant comment faire du REST dans Jelix.

6.4.1 Le contrôleur

Nous avons vu qu’il existe 4 methodes GET, POST, DELETE, PUT dans le protocole HTTP. Il faut implémenter
donc 4 méthodes pour chacune d’elles dans un contrôleur.
Vous devez réaliser un contrôleur qui va implémenter l’interface jIRestController. Ce contrôleur ne pourra être utiliser
que pour faire du REST. Vous ne pourrez donc pas réaliser des méthodes pour des actions supplémentaires, autres que
les quatres imposées par l’interface jIRestController :

class exempleCtrl extends jController implements jIRestController {

function get(){

function post(){

function put(){

function delete(){

}
}

Dans ces méthodes, vous développez vos actions comme à l’accoutumée, en respectant la signification de ces mé-
thodes. En général, GET doit correspondre à un affichage d’une ressource, POST à sa création, PUT à sa modification,
et DELETE à sa suppression.
Jelix 1.0.6
Guide du développeur
29 / 225

Note : il est indispensable de déclarer que vous implémentez l’interface jIRestController. C’est en effet en analysant
le contrôleur que Jelix sait si vous faites du REST ou pas, ce qui change son comportement interne.

6.4.2 Appel

Comme la nature de l’action est indiquée dans la méthode HTTP, de l’extérieur vous n’avez en fait qu’une seule url,
donc qu’une seule action. C’est le type de la méthode HTTP indiquée dans la requête HTTP qui indiquera à Jelix
d’appeler l’une des 4 méthodes du contrôleur.
Aussi, quand vous voulez récupérer avec jUrl l’url de l’action qui correspond à votre contrôleur REST, vous ne devez
indiquer que le module et le nom du contrôleur, et ne pas mettre donc le nom d’une méthode.
Ainsi, l’action qui permet d’appeler les methodes contrôleur de l’exemple, est "leModule~exemple :" (si le module
est "leModule"). Notez qu’il faut mettre un " :" pour indiquer que l’on indique bien le nom du contrôleur, et non le
nom d’une méthode.
Avec l’url obtenu par jUrl : :get("leModule~exemple :"), vous pouvez alors appeler dans vos scripts javascripts, via
xmlHttpRequest par exemple, l’une des quatres méthodes du contrôleur, simplement en indiquant à xmlHttpRequest
que vous voulez utiliser GET, POST, DELETE ou PUT.

Note

Vous pouvez bien sûr faire du REST avec un contrôleur classique, en testant dans votre action, la valeur de $_SER-
VER[’REQUEST_METHOD’] qui indique le type de la méthode HTTP. Mais c’est peut être moins "sexy" que d’uti-
liser le procédé indiqué dans cette page pour implémenter du REST ;-)
Jelix 1.0.6
Guide du développeur
30 / 225

Chapitre 7

Les réponses classiques

Jelix fournit en standard un certain nombre d’objet de réponses pour renvoyer aux navigateurs des contenus dans des
formats courants. Ce chapitre les décrits.

7.1 Générer une page HTML

Pour récupérer une réponse xhtml/html, vous indiquez l’alias "html" à la méthode getResponse(). Vous récupérez
ainsi la réponse comme ceci :
$rep = $this->getResponse(’html’);

Vous avez alors dans $rep une instance de l’objet JResponseHtml.

7.1.1 Xhtml ou html

jResponseHtml est utilisé pour renvoyer par défaut une réponse au format XHTML. Mais le HTML est possible, en
l’indiquant via la méthode setXhtmlOutput :
$rep->setXhtmlOutput(true); // Réponse au format xhtml
$rep->setXhtmlOutput(false); // Réponse au format html

Par la suite, vous pouvez savoir si la réponse renverra du html ou du xhtml en appelant la méthode isXhtml().

7.1.2 Génération du contenu

L’objet jResponseHtml implémente des méthodes et propriétés pour manipuler le contenu (X)HTML.
Le source HTML d’une page est découpé en deux parties : la partie <head>, et la partie <body> :
Jelix 1.0.6
Guide du développeur
31 / 225

jResponseHTML s’occupe de générer le contenu de la balise <head>, à partir des informations données au travers de
ses méthodes. Par contre la génération du contenu de la partie <body> est de votre ressort, avec l’aide éventuellement
d’un template. Voyons tout ça en détails.

7.1.3 Modification de l’entête HTML

Pour modifier le contenu de la balise <head>, vous avez plusieurs méthodes et propriétés. Vous pouvez ainsi modifier
le titre du document, le "favicon", les urls des feuilles de styles et des scripts javascripts à lier au document, du CSS
Jelix 1.0.6
Guide du développeur
32 / 225

ou du javascript à inclure directement dans le <head>, ou encore les mots clés associés, la description de la page, et
autres metas. Voyons un exemple qui montre l’ensemble de ces possibilités :
$rep->title = "Le titre de mon document";

// génère une balise <script src="lib.js"....>


$rep->addJSLink(’lib.js’);

// génère une balise <script>alert....</script> qui sera incluse dans <head>


$rep->addJSCode(’alert("essai");’);

// génère une balise <link>


$rep->addCSSLink(’maFeuille.css’);

// génère une balise <style>


$rep->addStyle(’span’, ’font-weight:bold;’);

// ajoute une balise meta pour la description


$rep->addMetaDescription(’description’);

// ajoute une balise meta pour les mots clés


$rep->addMetaKeywords(’motclé motclé motclé’);

Notez que pour la méthode addCSSLink et addJSLink, vous pouvez indiquer un paramètre supplémentaire qui doit
être un tableau associatif, décrivant les attributs supplémentaires à mettre.
$rep->addCSSLink(’maFeuille.css’, array(’title’=>’design bleu’, rel=>’alternate ←-
stylesheet’));

Si vous voulez injecter du contenu spécifique dans la balise <head>, vous pouvez le faire via la méthode addHead-
Content()
$rep->addHeadContent(’<link rel="alternate" type="application/rss+xml" title=" ←-
Recent Changes" href="/feed.php" />’)

Si à un moment ou à un autre, vous voulez annuler les modification faites dans le head (par exemple, vous êtes dans
une zone qui est appelée par un module tierce que vous ne voulez pas/pouvez pas modifier), vous pouvez appeler la
méthode clearHtmlHeader(). Cette fonction vous permet d’effacer une partie du header de votre document html, en
indiquant quoi effacer : ’CSSLink’, ’Styles’, ’JSLink’, ’JSCode’ et/ou ’Others’.
$rep->clearHtmlHeader(array(’CSSLink’, ’Styles’));

Cela effacera les liens CSS (addCSSLink) et les balises <style> (addStyle).

7.1.4 Générer le contenu de la page HTML

jResponseHtml génère la balise <body>, mais c’est vous qui en contrôlez ses attributs et son contenu.
Pour définir les attributs de la balise <body>, vous pouvez utiliser la propriété bodyTagAttributes.
$rep->bodyTagAttributes = array(’onload’=>’bodyonload()’, ’class’=>’maincontent’);

Pour générer le contenu même de la balise body, vous avez deux choix : soit utiliser un template, soit utiliser la
méthode addContent().
Jelix 1.0.6
Guide du développeur
33 / 225

Générer avec un template

Pour utiliser un template, jResponseHtml propose deux propriétés :


– bodyTpl, qui doit contenir le sélecteur du template à utiliser
– body qui contient un objet jTpl permettant de "paramétrer" le template.
Exemple :
$rep->bodyTpl = ’myapp~main’;

$rep->body->assign(’person’,’Laurent’);

Le contenu généré par le moteur de template sera intégré entre les balises <body> et </body>.
Pour en savoir plus sur l’utilisation des templates, consultez le chapitre sur les templates.
Il se peut que vous ayez besoin d’ajouter du contenu en plus de celui produit par le template. Pour cela vous utiliserez
la méthode addContent(). Elle prend en paramètre une chaine pour lecontenu, et un booléen (facultatif) pour indiquer
si on veut que le contenu soit ajouté avant (true) ou après (false, valeur par défaut) le contenu du template.
$rep->addContent(’Mon contenu HTML après le template’);
$rep->addContent(’Mon contenu HTML avant le template’, true);

Notez que le contenu à ajouter peut être aussi le contenu de zones


$rep->addContent(jZone::get(’monmodule~uneZone’));

Générer avec un template principal et des "sous-templates"

Bien souvent, les pages d’un site ont un gabarit commun, et seules certaines zones changent (notament le contenu
principal) en fonction de l’action. Il y aura donc un template principal , définit comme on l’a vu précédemment, qui
ne contiendra que le contenu commun à toutes les pages, et dans chaque action on utilisera un autre template (un
"sous-template") pour générer le contenu spécifique, dont on injectera le résultat dans le template principal. Ce travail
peut être fait avec un template directement, ou au moyen d’une zone.
Et pour éviter que dans chaque action on définisse à chaque fois le template principal, les élements communs (feuilles
de style etc), on créera un objet réponse HTML qui héritera de jResponseHtml.
Pour savoir comment faire, lire la section sur la personnalisation de réponse commune.

générer sans template

Si vous ne voulez pas utiliser de template pour le body, alors il faut laisser la propriété bodyTpl à vide, et utiliser
seulement la méthode addContent() :
$rep->addContent(’contenu pour mon body’);

7.1.5 Autres paramètres de la réponses

Comme jResponseHtml est dérivé de jReponse, vous pouvez aussi influer sur les entêtes HTTP : le code "status" et
ajouter d’autres en-têtes.
$rep->setHttpStatus ("404", "Not Found");
$rep->addHttpHeader ("Date-modified", "....");
Jelix 1.0.6
Guide du développeur
34 / 225

Il y a aussi une autre propriété, propre à jResponseHtml : xhtmlContentType. Cette propriété défini si le contenu
xHTML doit être envoyé avec une entête HTTP Content-Type spécifique : application/xhtml+xml. Bien sûr, une
vérification des capacités du navigateur à recevoir du xhtml est faites, et si le navigateur ne peut pas recevoir du
xHTML, la réponse sera envoyée avec le Content-Type text/html comme pour le HTML classique.
$rep->xhtmlContentType = true ;

7.2 Faire une redirection

Il existe deux types d’objets de redirection possible :


– jResponseRedirect : redirige vers une action de l’application avec la possibilité de passer des paramètres
– jResponseRedirectUrl : redirige vers une URL quelconque, en particulier une URL externe à votre application
jelix

7.2.1 jResponseRedirect

Pour spécifier une redirection vers une action, vous indiquez le type ’redirect’. Vous récupérez la réponse comme
ceci :
$rep = $this->getResponse(’redirect’);

Vous avez alors dans $rep une instance de l’objet jResponseRedirect.


Vous avez ensuite trois propriétés sur cet objet :
– action pour indiquer l’action vers laquelle rediriger
– params pour indiquer les paramètre d’une action (tableau associatif)
– anchor pour indiquer la partie "ref" de l’url (#anchor)
Exemple :
$rep->action = "module~controleur:action";
$rep->params = array(’foo’ => ’bar’);
$rep->anchor = ’yo’;

Définir ces propriétés est facultatif. Ainsi, si on n’indique pas l’action, ce sera l’action actuelle.
Et ensuite il n’y a plus qu’à renvoyer la réponse.
return $rep;

7.2.2 jResponseRedirectUrl

Pour spécifier une redirection vers une URL quelconque, vous indiquez le type ’redirectUrl’. Vous récupérez la
réponse comme ceci :
$rep = $this->getResponse(’redirectUrl’);

Vous avez alors dans $rep une instance de l’objet jResponseRedirectUrl. Cet objet possède une unique propriété,
url qui doit contenir une chaine, l’url de la page vers laquelle rediriger (en général, il s’agira d’une url externe à
l’application jelix, jResponseRedirect étant plus approprié pour les urls vers l’application jelix).
$rep->url = "http://jelix.org";
return $rep;
Jelix 1.0.6
Guide du développeur
35 / 225

7.3 Générer du texte brut

Il faut utiliser jResponseText qui est récupérable via l’alias "text". Cet objet possède une propriété "content" dans
laquelle vous mettez le texte voulu.
function myaction(){
$rep = $this->getResponse(’text’);
$rep->content = ’my text’;
return $rep;
}

Par défaut, jResponseText renvoi le type mime text/plain et avec le charset indiqué dans la config de jelix.
Toutefois, comme jResponseText dérive de jResponse, vous pouvez modifier les en-tête http, donc le type mime et
le charset.
D’ailleurs, jResponseText peut-être utilisé comme base pour d’autres formats à contenu textuels (json ou autre ré-
ponse pour ajax par ex).

7.4 Générer du XML quelconque

jResponseXML permet de renvoyer au navigateur du XML. Son alias est "xml"


$rep = $this->getResponse(’xml’);

Pour indiquer le contenu xml, vous avez deux possibilités.


– *Attention** : dans les deux cas, le XML doit être bien formé. Si ce n’est pas le cas, la réponse sera une erreur.

7.4.1 Générer à partir d’un template

Par défaut, la propriété $content contient un objet jTpl. Vous devez indiquer le sélecteur de template dans la propriété
$contentTpl.
$rep->contentTpl = ’monMOdule~monxml’;
$rep->content->assign(’foo’,’bla bla bla’);

jResponseXml s’occupe de générer la balise "< ?xml ?>" donc vous n’avez pas à vous en occuper dans le template.
Cependant, si le template comporte déjà cette balise, il faudra alors faire un
$rep->sendXMLHeader = false;

7.4.2 Génération sans template

Si vous ne voulez pas utiliser un template, vous mettez le contenu xml, sous forme de chaine, dans la propriété
$content.
$rep->content = ’<mondoc> <title>jelix</title> </mondoc>’;

jResponseXml s’occupe de générer la balise "< ?xml ?>" donc vous n’avez pas à vous en occuper. Cependant, si le
template comporte déjà cette balise, il faudra alors faire un
$rep->sendXMLHeader = false;
Jelix 1.0.6
Guide du développeur
36 / 225

7.4.3 Indiquer des feuilles de styles.

Vous pouvez attachez des feuilles de styles CSS ou XSLT au document XML produit. Pour cela, vous devez utili-
sez les méthodes addCSSStyleSheet() ou addXSLStyleSheet(). Elles prennent toutes deux en premier argument l’url
du fichier, et en deuxième argument optionnel un tableau associatif définissant les pseudo attributs à mettre sur la
processing instruction générée.
$rep->addCSSStyleSheet(’my.css’, array(’title’=>’super jolie’));
$rep->addXSLStyleSheet(’my.xsl’);

7.5 Générer un flux de syndication RSS

Jelix permet de générer un fil RSS assez facilement grâce à jResponseRss20. Cet objet prend en charge totalement la
spécification RSS 2.0. Comme tout type de réponse, la première chose à faire est de récupérer l’objet jResponseRss20
(alias "rss2.0").
$rep = $this->getResponse(’rss2.0’);

7.5.1 Informations sur le fil rss

jReponseRss20 possède tout d’abord une propriété infos, qui est un objet permettant de spécifier les propriétés du fil
RSS : son titre, l’url du site, le copyright, la description etc. Exemple :
$rep->infos->title = ’Actualité de Jelix’;
$rep->infos->webSiteUrl= ’http://jelix.org/fr/’;
$rep->infos->copyright = ’Copyright 2006-2008 jelix.org’;
$rep->infos->description = ’Actualité sur le framework PHP5 Jelix’;
$rep->infos->updated = ’2007-06-08 12:00:00’;
$rep->infos->published = ’2007-06-08 12:00:00’;
$rep->infos->ttl=60;

Les champs updated et published sont des dates qui indiquent respectivement la date de dernière mise à jour du fil
RSS, et la date de publication du channel RSS. On peut mettre la même date. Ces dates sont en générale déterminées
par la date de publication de l’item le plus récent qui sera présenté dans le fil. Par exemple, pour un fil RSS d’un blog,
ce sera la date du dernier billet.
La propriété ttl indique à l’aggrégateur de l’utilisateur, la durée (en minute) pendant laquelle il peut mettre le contenu
en cache avant de redemander le fil RSS.
Par défaut, la description doit être du texte normal. Cependant vous pouvez indiquer du HTML ou XHTML. Dans
ce cas vous devez l’indiquer dans la propriété descriptionType, qui peut prendre la valeur "html", "xhtml" ou "text".

7.5.2 Informations sur les items

Il faut ensuite remplir le channel avec les items que vous voulez publier. Pour un blog par exemple, les items seront
les descriptifs des derniers billets publiés.
Pour chaque item, vous devez appeler la méthode createItem() de jResponseRss20 pour récupérer un objet qui
contiendra les informations de l’item. Vous remplissez alors cet objet et vous le stockez dans l’objet jResponseRss20
avec la méthode addItem()
Voici un exemple avec une dao de news :
Jelix 1.0.6
Guide du développeur
37 / 225

$newsdao = jDao::get(’news’);
$first = true;

// ici on récupère la liste des 10 dernières news


// on suppose que la liste est classé de la plus récente à la moins récente
// (méthode définie dans la dao)
$list = $newsdao->findTenFirstNews();

foreach($list as $news){

if($first){
// le premier enregistrement permet de connaitre
// la date du channel
$rep->infos->updated = $news->date_create;
$rep->infos->published = $news->date_create;
$first=false;
}

// on récupère l’url de l’article de news


$url = jUrl::get(’news~default:article’, array(’newsid’=>$news->id));

// on crée un item RSS, en donnant un titre, une url, une date au format [yyyy ←-
-mm-jj hh-mm-ss]
$item = $rep->createItem($news->title, $url, $news->date_create);

// auteur de la news
$item->authorName = $news->author;

// contenu HTML de la news


$item->content = $news->content;
$item->contentType=’html’;

//dans notre exemple, on dit que l’url de la news est considéré


// comme étant l’id de la news
// dans le cas contraire, on aurait pu mettre $item->id =$news->id
$item->idIsPermalink = true;

// on ajoute l’item dans le fil RSS


$rep->addItem($item);
}

7.5.3 Autres informations

Il est possible d’indiquer plus d’informations sur le fil rss ou sur chaque item. Consultez la documentation de refe-
rence sur les objets jRSS20Info et jRSSItem.

7.6 Générer un flux de syndication Atom

Jelix permet, en plus de RSS, de pouvoir générer un fil Atom 1.0. Pour cela il faut utiliser l’objet jResponseAtom10,
qui prend en charge quasiement la totalité de la spécification Atom 1.0. Son alias est "atom1.0".
$rep = $this->getResponse(’atom1.0’);
Jelix 1.0.6
Guide du développeur
38 / 225

La manipulation de jResponseAtom10 est identique à jResponseRss20. La difference se situe sur quelques propriétés
dans les informations du fil ou des items.

7.6.1 Informations sur le fil atom

jResponseAtom10, comme jresponseRss20, possède une propriété infos, qui est un objet permettant de spécifier les
propriétés du fil Atom. Exemple :
$rep->infos->title = ’Actualité de Jelix’;
$rep->infos->webSiteUrl= ’http://jelix.org/fr/’;
$rep->infos->copyright = ’Copyright 2006-2007 jelix.org’;
$rep->infos->description = ’Actualité sur le framework PHP5 Jelix’;
$rep->infos->updated = ’2007-06-08 12:00:00’;
$rep->infos->selfLink=jUrl::get();

Le champs updated est la date de dernière mise à jour du fil Atom. Elle est en générale déterminée par la date de
publication de l’item le plus récent qui sera présenté dans le fil. Par exemple, pour un fil Atom d’un blog, ce sera la
date du dernier billet.
La propriété selfLink est l’url de ce fils Atom.
Par défaut, la description doit être du texte normal. Cependant vous pouvez indiquer du HTML ou XHTML. Dans
ce cas vous devez l’indiquer dans la propriété descriptionType, qui peut prendre la valeur "html", "xhtml" ou "text".

7.6.2 Informations sur les items

Il faut ensuite remplir le channel avec les items que vous voulez publier. Pour un blog par exemple, les items seront
les descriptifs des derniers billets publiés.
Pour chaque item, vous devez appeler la méthode createItem() de jResponseAtom10 pour récupérer un objet qui
contiendra les informations de l’item. Vous remplissez alors cet objet et vous le stockez dans l’objet jResponseAtom10
avec la méthode addItem()
Voici un exemple avec une dao de news :
$newsdao = jDao::get(’news’);
$first = true;

// ici on récupère la liste des 10 dernières news


// on suppose que la liste est classé de la plus récente à la moins récente
// (méthode définie dans la dao)
$list = $newsdao->findTenFirstNews();

foreach($list as $news){

if($first){
// le premier enregistrement permet de connaitre
// la date du channel
$rep->infos->updated = $news->date_create;
$first=false;
}

// on récupère l’url de l’article de news


$url = jUrl::get(’news~default:article’, array(’newsid’=>$news->id));

// on crée un item ATOM, en donnant un titre, une url, une date


Jelix 1.0.6
Guide du développeur
39 / 225

$item = $rep->createItem($news->title, $url, $news->date_create);

// auteur de la news
$item->authorName = $news->author;

// résumé de la news en HTML


$item->summary = $news->summary;
$item->summaryType=’html’;

// contenu HTML de la news


$item->content = $news->content;
$item->contentType=’html’;

// on ajoute l’item dans le fil ATOM


$rep->addItem($item);
}

7.6.3 Autres informations

Il est possible d’indiquer plus d’informations sur le fil atom ou sur chaque item. Consultez la documentation de
reference sur les objets jAtom10Info et jAtom10Item.

7.7 Générer un PDF à partir d’un contenu LaTeX

Jelix propose un objet jResponseLatexToPdf qui permet de générer un document PDF à partir d’un document écrit
en LaTeX. Son alias est "ltx2pdf".
$rep = $this->getResponse("ltx2pdf");

– *Note : L’utilisation de jResponseLatexToPdf nécessite la présence du programme pdflatex sur le serveur !**
Si ce programme n’est pas situé dans les chemins reconnus par le système (définis par la variable d’environnement
PATH sous Linux par exemple), il faut indiquer son chemin complet dans la propriété $pdflatexPath. Exemple :
$rep->pdflatexPath = ’/usr/bin/pdflatex’;

jResponseLatexToPdf s’occupe de générer un entête LaTeX comprenant le titre du documents et les auteurs, le reste
est à définir (en LaTeX) dans un template que vous indiquerez dans la propriété $bodyTpl. Et vous accédez au moteur
de template via la propriété $body.
Il y a aussi la méthode addCommand qui permet d’ajouter des commandes LaTeX au début du document.
Exemple :
$rep = $this->getResponse("ltx2pdf");

$rep->title = ’titre du document’;


$rep->authors[] = ’Michel Dupont’;
$rep->bodyTpl = ’monModule~doclatex’;

$rep->addCommand(’documentclass’, ’article’, array(’a4’, ’14pt’));


$this->addCommand(’geometry’, ’hmargin=1cm, vmargin=2cm’);

$rep->body->assign(’texte’, $unTexte);

return $rep;
Jelix 1.0.6
Guide du développeur
40 / 225

7.8 Générer un PDF avec TCPDF

Un objet jResponseTcpdf est fourni depuis la version 1.0, permettant de générer un PDF à partir de la classe TCPDF
(qui est une version améliorée de la célèbre FPDF).
Pour l’utiliser, vous devez d’abord télécharger les fontes disponibles sur le site de Jelix (Elles ne sont pas fournies
avec Jelix à cause de leur poids), et les installer dans lib/pdf-fonts/.
Ensuite dans une action :
$rep = $this->getResponse(’tcpdf’);

$rep->outputFileName = ’article.pdf’;
$rep->doDownload = true;

// initialise l’objet tcpdf


$rep->initPdf();
$rep->tcpdf->AddPage();
$rep->tcpdf->SetTitle(’un titre’);
$rep->tcpdf->Text(10,10,’un texte’);
...
return $rep;

L’objet dans la propriété tcpdf est tout simplement un objet TCPDF. Voir la documentation de TCPDF pour savoir
l’utiliser et connaître son API.
Pour utiliser son propre objet tcpdf (parce que l’on veut surcharger par exemple certaines méthodes de TCPDF :
$rep = $this->getResponse(’tcpdf’);

$rep->outputFileName = ’article.pdf’;
$rep->doDownload = true;

// initialize l’objet tcpdf


$rep->tcpdf = new MyTcPdf();
$rep->tcpdf->AddPage();
$rep->tcpdf->SetTitle(’un titre’);
$rep->tcpdf->Text(10,10,’un texte’);
...
return $rep;

MyTcPdf étant l’objet qui hérite de TCPDF.

7.9 Renvoyer un fichier binaire

Pour renvoyer un fichier binaire (un exécutable, une image, une video, une archive ou autre), il faut utiliser jRepon-
seBinary dont l’alias est "binary"
$rep = $this->getResponse(’binary’);

En premier lieu, ill vous faut indiquer dans la propriété $outputFileName le nom de fichier sous lequel apparaitra le
contenu, à l’utilisateur.
$rep->outputFileName = ’truc.gif’;

Vous pouvez aussi définir le type mime du contenu :


Jelix 1.0.6
Guide du développeur
41 / 225

$rep->mimeType = ’image/gif’;

Et vous devez aussi spécifier si le fichier doit être proposé à l’utilisateur pour l’enregistrement ou non. Pour des
fichiers couramment pris en charge par les navigateur (les images par exemple), on mettra false :
$rep->doDownload = false;

Ensuite pour le contenu, vous pouvez indiquer soit un fichier existant, soit du contenu que vous générez vous même.
Pour renvoyer un fichier existant :
$rep->fileName = JELIX_APP_VAR_PATH.’fichier_a_renvoyer.gif’;

Et sinon, si vous générez vous même, mettez le contenu dans une chaîne et mettez le dans $content :
$rep->content = ’...’;

7.10 Générer un fichier zip

Jelix propose jResponseZip qui permet de générer un fichier zip à la volée, et le proposer en téléchargement à
l’utilisateur. L’alias est "zip" :
$rep = $this->getResponse(’zip’);

Vous devez ensuite indiquer un nom de fichier. C’est sous ce nom que le contenu zip sera proposé à l’utilisateur. Ce
nom de fichier n’est pas forcément celui d’un fichier existant sur le serveur.
$rep->zipFilename=’myCrazyPackage.zip’;

Ensuite, il faut créer le zip. La propriété $content est un objet jZipCreator, dont vous utiliserez les méthodes pour
ajouter du contenu dans le zip. (Voyez la documentation de référence sur jZipCreator).
// ajoute le contenu du fichier datas/truc.txt stocké sur le serveur,
// et le réference dans le zip sous le nom machin.txt
$rep->content->addFile(JELIX_VAR_PATH.’datas/truc.txt’, ’machin.txt’);

// ajoute tout le contenu d’un répertoire "exemples" stocké sur le serveur


$rep->content->addDir(JELIX_VAR_PATH.’exemples/’, ’exemples’, true);

// créer un fichier dans le zip, avec le nom et le contenu donné


$rep->content->addContentFile(’dynamic.txt’, ’contenu généré comme on veut’);

Et c’est tout :-) L’utilisateur se verra proposer d’enregistrer sur son disque un fichier myCrazyPackage.zip, qui
contiendra un fichier machin.txt, un répertoire exemples, et un fichier dynamic.txt.

7.11 Générer une interface utilisateur en XUL

7.11.1 Qu’est ce que XUL ?

XUL est un langage de description d’interface utilisateur. Il peut être très utile pour réaliser des applications web
ayant l’ergonomie d’une application desktop, sans avoir à inclure des scripts JS et de faire du DHTML partout.
Voir http ://xulfr.org. XUL est utilisé dans Firefox pour son interface utilisateur. Notez qu’il faut obligatoirement un
navigateur basé sur le moteur Gecko de Mozilla (dont Firefox) pour pouvoir afficher du XUL.
Jelix 1.0.6
Guide du développeur
42 / 225

7.11.2 jResponseXul et cie

L’objet jResponseXul permet de générer une fenêtre XUL (<window>). Il y a aussi jResponseXulDialog pour les
boîtes de dialogue (<dialog>), jResponseXulOverlay pour les overlays XUL (<overlay>), et jResponseXulPage pour
les pages XUL incluses via une balise <iframe> dans une fenêtre XUL. Chacun de ces objets ont la même API (tous
basés sur jResponseXul), il y a seulement quelques différences minimes, au niveau notamment de la balise principale
générée.
jResponseXul permet de générer, comme jResponseHtml, les liens vers les feuilles de styles et les scripts javascript,
la balise principale, et les liens des overlays, qu’ils soient statiques ou dynamiques (voir plus loin).

7.11.3 Utilisation de jResponseXUL

Voici les alias pour récupérer les différentes réponses XUL :


$window = $this->getResponse("xul");
$dialog = $this->getResponse("xuldialog");
$overlay = $this->getResponse("xuloverlay");
$page = $this->getResponse("xulpage");

Dans la suite, on utilisera $window mais les exemples fonctionnent aussi avec les autres objets (sauf indication
contraire).
Vous pouvez indiquer des attributs à mettre sur la balise principale (<window>, <overlay>, <dialog> ou <page>) :
$window->rootAttributes = array("width"=>"300");

Pour lier la page XUL avec des feuilles de styles, des scripts et des overlays, il suffit d’utiliser les méthodes addCss-
Link(), addJsLink() et addOverlay() :
$window->addCssLink(’style.css’);
$window->addJsLink(’scripts.js’);
$window->addOverlay(’overlay.xul’);

Générer sans template

Si vous ne voulez pas utiliser de template, vous pouvez tout simplement utiliser la methode addContent pour ajouter
du XUL dans la page :
$rep->addContent(’contenu xul’);

Générer avec un template

Dans la propriété $body vous avez un objet jTpl, et vous devez indiquer dans la propriété $bodyTpl le sélecteur du
template à utiliser. Et $title permet d’indiquer le titre de la fenêtre :
$window->title = "ma fenêtre";
$window->bodyTpl = "monmodule~listexul";
$window->body->assign("liste", $liste);

Comme pour jResponseHtml, vous pouvez inclure du contenu avant ou après celui du template. Pour cela vous
utiliserez la méthode addContent(). Elle prend en paramètre une chaine pour le contenu, et un booléen (facultatif)
pour indiquer si on veut que le contenu soit ajouté avant (true) ou après (false, valeur par défaut) le contenu du
template.
Jelix 1.0.6
Guide du développeur
43 / 225

$rep->addContent(’Mon contenu XUL après le template’);


$rep->addContent(’Mon contenu XUL avant le template’, true);

Notez que le contenu à ajouter peut être aussi le contenu de zones

7.11.4 Réaliser des overlays

Un overlay est un fichier XUL qui permet d’ajouter des modifications à une autre page XUL sans toucher à son code
source. C’est très utilisé dans Firefox par les extensions. Cela peut être aussi utilisé dans une application web, et en
particulier dans Jelix : un module peut déclarer un overlay pour une page XUL générée par un autre module.

principe

La façon dont ça fonctionne est assez simple et repose sur le système d’évènement de Jelix. En fait un objet jRes-
ponseXul, avant de générer le contenu final, envoi un évènement pour se signaler. En réponse, les modules peuvent
lui renvoyer l’url d’un overlay. Une balise < ?xul-overlay ?> sera ajoutée alors dans la page.
Une condition pour que ça fonctionne vraiment : il faut que l’action qui génère la page xul mette la propriété $fet-
chOverlays à true :
$window->fetchOverlays = true;

Dans le cas contraire (et c’est le comportement par défaut), aucun évènement ne sera envoyé et donc aucun overlay
"étranger" ne pourra être indiqué.

mise en oeuvre

Tout d’abord, il faut faire une action qui génère une réponse "xuloverlay", comme vous l’avez vu plus haut. Imaginons
qu’il s’agisse de l’action "testa~xul :overlay1" et que l’action qui affiche la page xul sur laquelle s’applique l’overlay
soit "testb~xul :index".
Dans le module "testa", il faut ensuite faire un "listener" pour pouvoir répondre à l’évènement "FetchXulOverlay"
qu’envoie jResponseXul quand il demande les overlays à lier. Dans un fichier classes/testa.listener.php, vous aurez
alors :
class testaListener extends jEventListener{

function onFetchXulOverlay($event){

}
}

L’évènement a un paramètre, "tpl", qui indique le sélecteur de template utilisé pour la page principal générée par
l’action "testb~xul :index". Admettons qu’il s’agisse de "testb~mainxul". On va tester si le paramètre est bien le
template que l’on attend, et en retour, on va indiquer l’url de l’overlay.
class testaListener extends jEventListener{

function onFetchXulOverlay($event){
if($event->getParam(’tpl’) == ’testb~mainxul’){
$event->Add(’testa~xul:overlay1’);
}
}
}
Jelix 1.0.6
Guide du développeur
44 / 225

N’oublions pas de déclarer ce listener dans le fichier events.xml du module test a :


<events xmlns="http://jelix.org/ns/events/1.0">
<listener name="testa">
<event name="FetchXulOverlay" />
</listener>
</events>

Voilà, vous pouvez de cette manière modifier l’écran XUL du module testb sans toucher à son template xul.

7.12 Générer du RDF

jResponseRdf permet de générer un document au format RDF. Cela est utile entre autre lors de la réalisation d’ap-
plication en XUL, pour les templates XUL. Son alias est "rdf".
Vous avez deux moyens d’utiliser jResponseRdf :
– soit vous fournissez une liste de données et la classe s’occupe de générer du RDF
– soit vous écrivez vous même le code RDF dans un template, ce qui est nécessaire pour les graphes RDF complexes.

7.12.1 Génération automatique de RDF

Cela ne fonctionne que pour les RDF qui representent qu’une liste simple de données (pas de sous arbres par
exemple).
Vous indiquez la liste des données au niveau de la propriété $datas : cela peut être une liste de tableaux associatifs,
un objet jResultSet (iterateur) que retourne jDb : :query ou les méthodes de type "select" des daos.
$rep = $this->getResponse("rdf");

$dao = jDao::get(’users’);
$rep->datas = $dao->findAll();

Ou encore
$rep->datas = array(
array(’nom’=>’dupont’, ’prenom’=>’georges’),
array(’nom’=>’durant’, ’prenom’=>’paul’),
array(’nom’=>’duchemin’, ’prenom’=>’jacques’),
);

Ce dernier exemple va générer le RDF suivant :


<RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:row="http://dummy/rdf#">

<Bag RDF:about="urn:data:row">
<li><Description>
<row:nom>dupont</row:nom>
<row:prenom>georges</row:prenom>
</Description></li>
<li><Description>
<row:nom>durant</row:nom>
<row:prenom>paul</row:prenom>
</Description></li>
<li><Description>
Jelix 1.0.6
Guide du développeur
45 / 225

<row:nom>duchemin</row:nom>
<row:prenom>jacques</row:prenom>
</Description></li>
</Bag>
</RDF>

jResponseRdf donne par défaut le namespace "http :dummy/rdf#" aux éléments contenant les données, namespace
déclaré avec le préfixe "row". Vous pouvez changer cela via respectivement les propriétés $resNs et $resNsPrefix//.
$rep->resNs = ’http://monsite.com/ns/users/’;
$rep->resNsPrefix = ’user’;

Vous pouvez aussi changer l’identifiant de la liste qui est par défaut "urn :data :row" :
$rep->resUriRoot = ’urn:monsite:users’;

Enfin, pour diverses raisons, vous voudriez peut être mettre certaines informations en tant qu’attributs, et d’autres en
tant qu’elements. Il faut alors l’indiquer via les propriétés $asElement et $asAttribute.
$rep->asAttribute = array(’prenom’);
$rep->asElement = array(’nom’);

Note : à partir du moment où vous changez l’une de ces deux propriétés, il faut alors indiquer tous les noms des
données que vous voulez voir apparaitre dans le RDF.
Cela donne alors :
<RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:user="http://monsite.com/ns/users/">

<Bag RDF:about="urn:monsite:users">
<li><Description user:prenom="georges">
<user:nom>dupont</user:nom>
</Description></li>
<li><Description user:prenom="paul">
<user:nom>durant</user:nom>
</Description></li>
<li><Description user:prenom="jacques">
<user:nom>duchemin</user:nom>
</Description></li>
</Bag>
</RDF>

7.12.2 Génération à partir d’un template

L’autre façon d’utiliser jResponseRdf est de passer par un template pour générer le contenu RDF. Vous devez indiquer
les données pour le template via la propriété $datas, elles seront ainsi disponible via la variable de template "datas".
Et vous devez indiquez le sélecteur du template dans la propriété $template.
$rep = $this->getResponse("rdf");

$rep->datas = array(
array(’nom’=>’dupont’, ’prenom’=>’georges’),
array(’nom’=>’durant’, ’prenom’=>’paul’),
array(’nom’=>’duchemin’, ’prenom’=>’jacques’),
);
$rep->template = ’monmodule~datasrdf’;
Jelix 1.0.6
Guide du développeur
46 / 225

Et dans datasrdf.tpl :

<RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:user="http://monsite.com/ns/users/">

<Bag RDF:about="urn:monsite:users">

{foreach $datas as $dt}


<li><Description user:prenom="{$data[’prenom’]|escxml}">
<user:nom>{$data[’nom’]|escxml}</user:nom>
</Description></li>
{/foreach}

</Bag>
</RDF>

Note : vous n’avez pas à mettre le prologue xml (< ?xml... )


Note : les propriétés $resNs, $resNsPrefix, $resUriRoot, $asElement et $asAttribute sont inutiles dans le cas de
l’utilisation d’un template.
Jelix 1.0.6
Guide du développeur
47 / 225

Chapitre 8

Services web

Outre les contenus classiques que l’on peut fournir aux navigateurs (HTML, XML etc), Jelix permet également
d’implémenter des services web, que ce soit pour de l’Ajax, en JSON, ou pour fournir des services plus évolués en
XML-RPC ou SOAP (SOAP est prévu pour Jelix 1.1).
Une des particularités de développer des services web dans Jelix, est que le principe de développement reste le même
que pour les contenus classiques : vous récupérez un objet réponse, vous lui donnez des paramètres, et Jelix s’occupe
du reste. Vous n’avez pas à connaître le format précis du protocole du services web utilisé, à gérer les entête HTTP
etc.
La seule différence est que pour certains type de services web, vous devez avoir un point d’entrée spécifique au type
de services web (donc, autre que index.php).

8.1 AJAX

Bien que le terme AJAX précise qu’une réponse doit être en XML (d’où le X dans AJAX), AJAX est souvent utilisé
avec d’autres types de format.
Selon ce que vous attendez côté client, soit dans la propriété responseText, soit dans la propriété responseXml de
l’objet xmlHttpRequest, vous utiliserez un objet jResponse différent.
– Pour tout ce qui est contenu XML quelconque, vous utiliserez jResponseXml
– Pour des réponses en JSON, vous utiliserez jResponseJson
– Pour renvoyer des fragments de code HTML, il ne faut pas utiliser jResponseHtml, mais jResponseText (voir
exemple ci-dessous).
– En règle générale, vous utiliserez jResponseText.

8.1.1 Renvoyer des fragments de code HTML

Il ne faut pas utiliser jResponseHtml, car cet objet génère tout ce qu’il faut pour une page HTML : le <head>, le
<body> etc... Bien souvent, dans une requête AJAX, on ne veut récupérer qu’un fragment de code HTML.
jResponseText est plus adapté pour cela (dans la version 1.1, il y aura jResponseHtmlFragment) :
$rep = $this->getResponse(’text’);
$rep->content = ’<p>nouvelle donnée</p>’;
return $rep;
Jelix 1.0.6
Guide du développeur
48 / 225

Note à propos de l’utilisation de jforms dans des réponses Ajax

Il y a un souci connu quand on utilise un formulaire jforms dans un template pour une réponse autre que html pour
faire une réponse ajax : il peut y avoir une erreur PHP qui dit que l’objet response n’a pas la méthode addJsLink.
En effet, pour fonctionner correctement, un formulaire jforms a besoin de la présence du fichier lib/jelix-www/js/jforms.js
dans la page qui appelle la requête ajax. Ce fichier est inclus automatiquement par le plugin form, en appelant la me-
thode addJsLink de la réponse. Malheureusement, il manque un test d’existance de cette méthode. Ce bug sera corrigé
dans la version 1.0.4.
Autre chose, même si ce bug n’existait pas, il reste un problème : comme les fragments HTML renvoyé par les
reponses ajax n’ont pas d’entête HTML <head>, le script n’est pas inclus dans la page html final, ce qui causera des
erreurs javascript. Pour le moment, il n’y a pas d’autres solutions que d’inclure ce script jforms.js "à la main" lors de
la génération de la page hôte (celle qui fait donc la requête ajax).

8.2 JSON

JSON est un format de données qui réutilise des éléments syntaxique de Javascript. Cela facilite alors grandement
l’utilisation de contenu en JSON dans une page HTML. C’est de plus en plus utilisé pour la technique AJAX.
Pour envoyer un contenu en JSON au navigateur, vous pouvez employer la réponse jResponseJson dont l’alias est
"json". Vous n’avez ensuite qu’à mettre n’importe quelles données dans la propriété $datas.
$rep = $this->getResponse(’json’);
$rep->datas = array( ’nom’=>’dupont’, ’prenom’=>’jean’);

Vous recevrez alors coté client, ceci :


{ nom: ’dupont’, prenom:’jean’}

– *Exemple d’utilisation avec une DAO**


$countryDao = jDao::get(’common~country’);
$countries = $countryDao->findAll();
$response = $this->getResponse(’json’);
$response->datas = array();
foreach($countries as $country) {
$response->datas[] = array(’id’ => $country->id , ’name’ => $country->name);
}

On récupére coté client des objets en notation JSON comme celui-ci :


{ id: ’1’, name:’Europe’}

8.3 JSON-RPC

Jelix propose la prise en charge du protocole json-rpc. Ce protocole d’échange est similaire à XML-RPC dans le
fonctionnement, mais utilise JSON comme format de donnée au lieu de XML (RPC = Remote Procedure Call).
Jelix 1.0.6
Guide du développeur
49 / 225

8.3.1 Point d’entrée spécifique

Une requête JSON-RPC est spécifique, et pour y répondre, on ne peut pas utiliser l’objet request "classic". Il vous
faut créer un point d’entrée spécifique dans le répertoire www, jsonrpc.php par exemple, qui utilise jJsonRpcRequest
plutôt que jClassicRequest. Le type de requête et du point d’entrée est donc "jsonrpc".
Le point d’entrée devra contenir ceci :
require_once (’../../lib/jelix/init.php’);
require_once (’../../VOTRE APPLI/application.init.php’);

$config_file = ’jsonrpc/config.ini.php’;

require_once (JELIX_LIB_CORE_PATH.’request/jJsonRpcRequest.class.php’);

$jelix = new jCoordinator($config_file);


$jelix->process(new jJsonRpcRequest());

Il ne faut pas oublier de déclarer ce point d’entrée au niveau de la configuration des moteurs d’urls simple ou
significant. Si vous utilisez le moteur d’url simple, vous devez mettre dans la section simple_urlengine_entrypoints
de la configuration de jelix la déclaration suivante :
jsonrpc = "@jsonrpc"

jsonrpc étant le nom du point d’entrée, et @jsonrpc indiquant le type de point d’entrée.
Si vous utilisez le moteur d’url significant, vous devez ajouter la balise suivante :
<jsonrpcentrypoint name="jsonrpc" default="true" />

Dans un cas comme dans l’autre, vous pouvez alors récupérer l’url d’une action pour jsonrpc comme ceci :
$url = jUrl::get("module~action@jsonrpc");

8.3.2 Contrôleur

Comme on a affaire à un type de requête particulier, le nom du fichier du contrôleur doit avoir le suffixe ".jsonrpc.php".
Par exemple, un contrôleur "default" : "default.jsonrpc.php". (Vous pouvez bien sûr avoir un autre contrôleur "default"
pour d’autres types de requêtes, "default.classic.php" par exemple).
Ensuite, le contenu du contrôleur est similaire à ce que vous avez l’habitude de faire, à la seule différence que vous
utiliserez jResponseJsonRpc, qui a pour alias "jsonrpc", pour répondre aux requêtes JsonRpc :
class defaultCtrl extends jController {

function index(){

$rep = $this->getResponse(’jsonrpc’);

// n’importe quelles types de données : entier, chaine, array, objets...


$donnees_php = ... ;

$rep->response = $donnees_php;

return $rep;

}
}
Jelix 1.0.6
Guide du développeur
50 / 225

8.3.3 Appel depuis le client

Qui dit JsonRpc, dit une partie cliente qui envoi une requête jsonrpc. Comme vous pouvez le lire dans la spécification
de jsonrpc, il faut envoyer une chaine de ce type :
{ method : "",
id:"",
params: {}
}

Dans method, vous indiquerez, dans le cas d’un appel à une application jelix, le sélecteur de l’action à appeler :
method:"monModule~default:index"

Les données que vous mettrez dans params seront mise dans le paramètre "params" dans la réponse. Ainsi, pour les
récupérer dans l’action vous ferez :
$parametres = $this->param(’params’);

Bien entendu, ce que vous avez dans $parametres sera des données "php" (chaine, array ou autre), la transformation
de la chaine json étant réalisée par jJsonRpcRequest..
Notez qu’un script javascript est fourni dans lib/jelix-www/json.js. Il vous permet, dans vos pages HTML de trans-
former vos données javascript en chaine json. Pour cela, sur les objets, tableaux et autre type de donnée javascript, il
suffit d’appeler la méthode javascript toJSONString() qui renvoi une chaine. Il suffit ensuite de passer cette chaine à
xmlHttpRequest pour envoyer la requête JSONRPC à jelix. Exemple, dans votre page HTML :
var jsonrpc = { method : "monModule~default:index",
id:"1",
params: null
};

var toSend = jsonrpc.toJSONString();


var p = new XMLHttpRequest();
p.onload = null;
p.open("POST", "http://monsite.tld/jsonrpc.php", false);
p.send(toSend);

var reponse = p.responseText.parseJSON();


var resultat = reponse.result;

Enfin si dans l’action jelix, vous avez fait un


$rep->response = "hello";

Vous aurez alors dans la variable resultat de l’exemple javascript, une chaine "hello".

8.4 XML-RPC

Jelix propose la prise en charge de xml-rpc. C’est un protocole d’échange de données en XML : un client envoie un
contenu XML indiquant une fonction à exécuter et des paramètres. Le serveur renvoie un résultat, toujours sous forme
de XML (RPC = Remote Procedure Call).
Jelix 1.0.6
Guide du développeur
51 / 225

8.4.1 Point d’entrée spécifique

Une requête XML-RPC est spécifique, et pour y répondre, on ne peut pas utiliser l’objet request "classic". Il vous
faut créer un point d’entrée spécifique dans le répertoire www, xmlrpc.php par exemple, qui utilise jXmlRpcRequest
plutôt que jClassicRequest. Le type de requête et du point d’entrée est donc "xmlrpc".
Le point d’entrée devra contenir ceci :
require_once (’../../lib/jelix/init.php’);
require_once (’../../VOTRE APPLI/application.init.php’);

$config_file = ’xmlrpc/config.ini.php’;

require_once (JELIX_LIB_CORE_PATH.’request/jXmlRpcRequest.class.php’);

$jelix = new jCoordinator($config_file);


$jelix->process(new jXmlRpcRequest());

Il ne faut oublier de déclarer ce point d’entrée au niveau de la configuration des moteurs d’urls simple ou signifi-
cant. Si vous utilisez le moteur d’url simple, vous devez mettre dans la section simple_urlengine_entrypoints de la
configuration de jelix la déclaration suivante :
xmlrpc = "@xmlrpc"

xmlrpc étant le nom du point d’entrée, et @xmlrpc indiquant le type de point d’entrée.
Si vous utilisez le moteur d’url significant, vous devez ajouter la balise suivante :
<xmlrpcentrypoint name="xmlrpc" default="true" />

Dans un cas comme dans l’autre, vous pouvez alors récupérer l’url d’une action pour xmlrpc comme ceci :
$url = jUrl::get("module~action@xmlrpc");

8.4.2 Contrôleur

Comme on a affaire à un type de requête particulier, le nom du fichier du contrôleur doit avoir le suffixe ".xmlrpc.php".
Par exemple, un contrôleur "default" : "default.xmlrpc.php". (Vous pouvez bien sûr avoir un autre contrôleur "default"
pour d’autres types de requêtes, "default.classic.php" par exemple).
Ensuite, le contenu du contrôleur est similaire à ce que vous avez l’habitude de faire, à la seule différence que vous
utiliserez jResponseXmlRpc, qui a pour alias "xmlrpc", pour répondre aux requêtes JsonRpc :
class defaultCtrl extends jController {

function index(){

$rep = $this->getResponse(’xmlrpc’);

// n’importe quelles types de données : entier, chaine, array, objets...


$donnees_php = ... ;

$rep->response = $donnees_php;

return $rep;

}
}
Jelix 1.0.6
Guide du développeur
52 / 225

8.4.3 Appel depuis le client

Qui dit XmlRpc, dit une partie cliente qui envoi une requête xmlrpc. Comme vous pouvez le lire dans la spécification
de xml-rpc, il faut envoyer du contenu XML de ce type :
<?xml version="1.0" ?>
<methodCall>
<methodName>module:default:index</methodName>
<params>
<param><string>Allo ?</string></param>
</params>
</methodCall>

Dans methodName, vous indiquerez, dans le cas d’un appel à une application jelix, le sélecteur de l’action à appeler,
comme ici "module :default :index".
Notez qu’il faut indiquer le caractère " :" plutôt que "~" comme séparateur du nom du module et du nom de l’action.
En effet, le caractère tilde "~" est interdit dans le nom de la méthode en xmlrpc. De ce fait, il faut obligatoirement
indiquer le module, le controleur et la méthode.
Les données que vous mettrez dans params seront mises dans le paramètre "params" dans la réponse jelix. Ainsi,
dans l’action, pour les récupérer dans l’action, vous ferez :
$parametres = $this->param(’params’);

Bien entendu, ce que vous avez dans $parametres sera des données "php" (chaine, array ou autre), la transformation
du contenu de la balise <params> étant réalisée par jXmlRpcRequest..
Exemple d’appel XMLRPC à partir d’un page HTML : à faire...
Jelix 1.0.6
Guide du développeur
53 / 225

Chapitre 9

Effectuer des traitements en ligne de commande

9.1 Introduction

Jelix vous permet de lancer des actions spécialement en ligne de commande. Ceci est très pratique pour effectuer des
traitements sur un serveur et de les planifier.

9.2 Installation

Pour lancer des actions en ligne de commande, il faut 3 éléments :


– un point d’entrée spécifique
– un controller cmdline
– un fichier de configuration pour la ligne de commande
Les jelix-scripts vont vous permettre de créer ces éléments facilement.

9.2.1 Création du point d’entrée

À l’aide des jelix-scripts

Il se créé au moment de la création de l’application :


$ php jelix.php createapp -withcmdline

Avec cette commande, vous allez créer la structure d’une nouvelle application qui contiendra en plus un répertoire
scripts contenant alors le point d’entrée cmdline : cmdline.php

Manuellement

Si vous avez déjà créé votre application vous pouvez créer le point d’entrée votre application/scripts/cmdline.php à
la main. Voici son contenu :
<?php

require_once (’../../lib/jelix/init.php’);

require_once (’.././application.init.php’);
Jelix 1.0.6
Guide du développeur
54 / 225

require_once (JELIX_LIB_CORE_PATH.’request/jCmdLineRequest.class.php’);

$config_file = ’cmdline/config.ini.php’;

$jelix = new jCoordinator($config_file);


$jelix->process(new jCmdLineRequest());

?>

9.3 Création d’un controller cmdline

Pour pouvoir travailler en mode cmdline, vous allez devoir créer un controller spécifique à la ligne de commande.

9.3.1 À l’aide des jelix-scripts

Vous pouvez créer votre controller en utilisant les jelix-scripts :


$ php jelix.php createmodule -cmdline foo // création du module foo avec un ←-
controller cmdline

ou
$ php jelix.php -cmdline foo bar // création du controller bar dans le module foo

9.3.2 Manuellement

Pour créer le controller manuellement, celui-ci ne devra pas hériter de jController comme habituellement, mais il
devra hériter de jControllerCmdline.
<?php

class defaultCtrl extends jControllerCmdLine {

function index() {
$rep = $this->getResponse(); // response text
$rep->content = "Hello, it works !";
return $rep;
}
}

?>

9.4 Création du fichier de configuration

Si vous avez créé l’application avec l’option -withcmdline le fichier de configuration aura été généré pour vous.
Voici son emplacement : app/var/config/cmdline/config.ini.php
Si le fichier n’existe pas, vous pouvez très simplement le créer à la main en prenant modèle sur le fichier de configu-
ration classic (app/var/config/index/config.ini.php)
Jelix 1.0.6
Guide du développeur
55 / 225

9.5 Développement d’actions

Pour lancer vos actions, vous allez certainement vouloir lui passer des paramètres et des options.

9.5.1 Options

Déclaration

Pour déclarer les options que l’on pourra passer à l’action en ligne de commande, il faut utiliser la variable de classe
$allowed_options qui est un tableau.
protected $allowed_options = array(
’nom_action’ => array(’-nom_option’ => true/false)
);

Si le nom de l’option vaut true cela signifie qu’une valeur est attendue après l’option.

Récupération

Dans les actions de votre controller cmdline vous allez vouloir récupérer les options passées au script. Pour cela il
faut utiliser la méthode option(’-nom_option’)
Exemple :
public function myscript() {
$myoption = $this->option(’-nom_option’);
}

9.6 Paramètres

9.6.1 Déclaration

Le mécanisme est le même pour les paramètres :


protected $allowed_parameters = array(
’nom_action’ => array(’nom_parametre’ => true/false)
);

Ici si le nom du paramètre vaut true c’est qu’il est obligatoire, false sinon.

9.6.2 Récupération

Dans les actions de votre controller cmdline vous allez vouloir récupérer les paramètres passés au script. Pour cela il
faut utiliser la méthode param(’-nom_option’)
Exemple :
public function myscript() {
$myparam = $this->param(’nom_parametre’);
}
Jelix 1.0.6
Guide du développeur
56 / 225

9.7 Message d’aide

Vous pouvez aussi gérer le message d’aide sur les commandes. Ceux-ci se déclare dans la variable de classe $help :
public $help = array(
’nom_action’ => ’message’
);

Nous allons dans la partie suivante comment se servir de ce message d’aide

9.8 Utilisation

Pour utiliser vos scripts, c’est à dire vos actions de vos controllers cmdline, rendez vous en ligne de commande dans
le répertoire app/scripts
Il suffit alors de lancer le script cmdline.php suivi de l’action à lancer (en utilisant le sélecteur d’action) et suivi
du/des options et du/des paramètres voulu
Exemple :
$ php cmdline.php module~controller:action -nom_option optionval nom_param

Pour afficher l’aide, il suffit de faire :


$ php cmdline.php jelix~help:index module~controller:action
Jelix 1.0.6
Guide du développeur
57 / 225

Chapitre 10

Définir des traitements communs à plusieurs ac-


tions

Il y a plusieurs types de traitements : les traitements métiers, et ceux dédiés à la génération de la page web. Pour les
traitements métiers, vous utiliserez des classes métiers, des classes services, des daos. Celles-ci pouvant être utilisable
par tous les modules, c’est un premier moyen de réaliser des traitements métiers qui puissent être réutilisables. Voir
classes-metiers.
Pour ce qui concerne la génération d’une page, c’est un peu plus complexe que ça car il y a plusieurs façons de faire.
Nous sommes donc devant le cas suivant : nous avons plusieurs pages qui ont des parties communes. Cela peut être
par exemple un bandeau, un pied de page, un menu sur le coté etc.. Il peut y avoir aussi quelques pages qui ont un peu
plus que ça en commun. Voici diverses solutions selon le contexte.
– Utilisation de méthodes privées de contrôleurs
– Héritage de contrôleurs
– Utilisation d’une réponse commune
– Utilisation de zones

10.1 Méthodes privées de contrôleurs

Si la similitude des pages se résume à quelques actions qui sont dans un même contrôleur, alors vous pouvez utiliser
une méthode privée/protégée, qui va faire le travail commun à toutes ces actions.

class defaultCtrl extends jController {

protected function common(){


$rep = $this->getResponse(’html’);
$rep->title = ’Même titre pour tout le monde’;
$rep->body->assign(’menu’, ’<ul><li>item 1</li><li>item 2</li></ul>’);
return $rep;
}

function index(){
$rep = $this->common();
$rep->body->assign(’MAIN’,’<p>Bienvenue sur cette application de test</p>’);
return $rep;
}
Jelix 1.0.6
Guide du développeur
58 / 225

function liste(){
$rep = $this->common();
$rep->body->assign(’MAIN’,’<ul><li>une</li><li>liste</li></ul>’);
return $rep;
}

Dans cette exemple, les deux actions index et liste font appel à une méthode commune qui va réaliser le travail
commun.

10.2 Héritage de contrôleurs

Si plusieurs actions de plusieurs contrôleurs ont des traitements en commun, alors vous pouvez utiliser le mécanisme
d’héritage objet. C’est à dire réaliser un contrôleur de base, qui ne sera pas utilisé directement, mais dont hériteront
les contrôleurs concernés.
Voici un exemple de contrôleur de base, dans le fichier controllers/myBaseController.php :
class myBaseController extends jController {

protected function common(){


$rep = $this->getResponse(’html’);
$rep->title = ’Même titre pour tout le monde’;
$rep->body->assign(’menu’, ’<ul><li>item 1</li><li>item 2</li></ul>’);
return $rep;
}

Et dans vos contrôleurs :


global $gJCoord;
include $gJCoord->getModulePath(’monModule’).’controllers/myBaseController.php’;

class defaultCtrl extends myBaseController {

function index(){
$rep = $this->common();
$rep->body->assign(’MAIN’,’<p>Bienvenue sur cette application de test</p>’);
return $rep;
}

function liste(){
$rep = $this->common();
$rep->body->assign(’MAIN’,’<ul><li>une</li><li>liste</li></ul>’);
return $rep;
}

}
Jelix 1.0.6
Guide du développeur
59 / 225

Notez l’include et le extends myBaseController ;


Bien sûr, le contrôleur de base peut contenir des propriétés, d’autres méthodes, voir même des méthodes d’actions.
C’est à dire que vous pouvez ainsi avoir plusieurs contrôleurs qui possèdent au final des actions communes (qui
peuvent elle-même tenir compte de propriétés ou d’autres méthodes pour gérer des différences).
Vous pouvez faire par exemple un contrôleur de base, qui définit une série d’actions : liste, creation, modification,
suppression. Ces actions se basant sur des propriétés pour savoir les daos et les templates à utiliser. Ainsi, il est aisé
de réaliser plusieurs contrôleurs, héritant de ce contrôleur de base, et n’ayant plus qu’à indiquer dans des propriétés
les daos et les templates. De quoi ainsi se faire une administration basique assez rapidement.

10.3 Personnalisation de réponse commune

Les deux solutions précédentes sont intéressantes pour des cas peu courants, ou du moins, pas généraux à l’applica-
tion. Si vous avez des choses en commun pour la majorité des actions, il est préférable de faire autrement : surcharger
un objet réponse.
Vous créerez cet objet response de façon à ce que ce soit lui qui fasse le travail commun à toutes les actions. Imaginons
par exemple que toutes les pages HTML de votre site ait le même menu dynamique, la même feuille de style etc..
Vous créerez donc une classe response comme il est indiqué dans générer un contenu personnalisé, et qui effectuera
ce travail.
Si vous voulez réaliser des modules réutilisables, cette façon de faire est d’autant plus intéressante puisqu’alors tout
ce qui ne concerne pas le module est réalisé à l’extérieur de ce module. Il est donc plus indépendant de l’application,
contrairement au cas où il gère lui même dans ses actions les parties communes des pages du site (bandeau etc...).
Vos propres classes de réponses peuvent hériter de jResponseHtml par exemple. Dans cette classe, vous pouvez
alors :
– surcharger le constructeur pour réaliser des choses qui seront fait lorsque vous ferez le getResponse dans votre
contrôleur
– surcharger la méthode _commonProcess. Notez que cette méthode n’existe que pour jResponseHtml. Elle sera
appelée aprés votre action, et juste avant l’affichage définitif.
Voyons plus précisément comment ça se gère globalement. Vous avez donc vos pages HTML, qui contiennent la
partie <head> et la partie <body> :
Jelix 1.0.6
Guide du développeur
60 / 225

Vous aurez un template principal qui s’occupe de générer l’ensemble du contenu de <body>, et ce template va être dé-
claré au niveau de votre propre objet response. Voici par exemple votre objet responses/myHtmlResponse.class.php :
require_once (JELIX_LIB_RESPONSE_PATH.’jResponseHtml.class.php’);

class myHtmlResponse extends jResponseHtml {

public $bodyTpl = ’myapp~main’;

protected function _commonProcess(){


Jelix 1.0.6
Guide du développeur
61 / 225

}
}

Votre page est en général découpé en zone :

Ainsi le template pourrait ressembler à ceci


<div id="header"> ... {$date} </div>
<div id="sidebar-left"> {$A} {$B} {$C} </div>
<div id="sidebar-right"> {$D} </div>
Jelix 1.0.6
Guide du développeur
62 / 225

<div id="main-content"> {$MAIN} </div>

<div id="footer"> ...</div>

Ces zones A, B, C, D et MAIN peuvent être générées par des sous-templates ou des objets jZone, materialisés ici par
des parties distinctes :

En particulier, la partie MAIN sera générée par un template que les actions fourniront.
Ainsi l’objet réponse pourra s’occuper par exemple de la partie A (si celle-ci est commune à toutes les pages), et les
autres zones seront remplies à loisir par les actions. Dans l’objet réponse on aura donc :
Jelix 1.0.6
Guide du développeur
63 / 225

require_once (JELIX_LIB_RESPONSE_PATH.’jResponseHtml.class.php’);

class myHtmlResponse extends jResponseHtml {

public $bodyTpl = ’myapp~main’;

protected function _commonProcess(){


// toutes les pages auront une zone de login affichée
$this->body->assignZone("A", "auth~login");

// et au cas où rien n’est défini pour B,C,D et MAIN, on met du contenu


// par défaut
$this->body->assignIfNone(’B’,’’);
$this->body->assignIfNone(’C’,’’);
$this->body->assignIfNone(’D’,’’);
$this->body->assignIfNone(’MAIN’,’<p>No content</p>’);

// on indique les autres variables


$this->body->assign(’date’, date(’Y-m-d’));
}
}

Dans les actions (contrôleurs), on fera donc des choses comme :


function mon_action() {
$rep = $this->getResponse(’html’);
// on indique du contenu pour B
$rep->assign(’B’,’<h2>Hello !</h2>’);

// on indique du contenu pour D


$rep->assignZone(’D’, ’ma_sidebar’);

// Pas de contenu pour C, donc on ne fait rien pour C

// on s’occupe maintenant de la partie principal


// qui a son propre template
$tplMain = new jtpl();
$tplMain->assign(...);
$rep->assign(’MAIN’, $tplMain->fetch(’monmodule~montpl’));

return $rep;
}

Bien sûr, la réponse peut définir aussi autre chose que le template : feuille de styles et cie. Ce qui évite de le faire
dans les actions. Exemple, en surchargeant le constructeur :
class myHtmlResponse extends jResponseHtml {

public $bodyTpl = ’myapp~main’;

// traitement executé AVANT les actions


public function __construct() {
parent::__construct();
$this->addCSSLink(’design/screen.css’);
}

// traitement executé APRES les actions


Jelix 1.0.6
Guide du développeur
64 / 225

protected function doAfterActions(){

$this->title .= ($this->title !=’’?’ - ’:’’).’ My App’;

// toutes les pages auront une zone de login affichée


$this->body->assignZone("A", "auth~login");

// et au cas où rien n’est défini pour B,C,D et MAIN, on met du contenu


// par défaut
$this->body->assignIfNone(’B’,’’);
$this->body->assignIfNone(’C’,’’);
$this->body->assignIfNone(’D’,’’);
$this->body->assignIfNone(’MAIN’,’<p>No content</p>’);

// on indique les autres variables


$this->body->assign(’date’, date(’Y-m-d’));
}
}

10.3.1 Déclaration de l’objet response

Cet objet response est déclaré comme ceci dans la configuration :


[responses]
html=myHtmlResponse

Toutes les actions qui feront alors appel à la réponse "html", fourniront un objet myHtmlResponse, et donc une page
avec un formulaire de login généré par la zone ’auth~login’, un contenu par défaut pour les variables de templates
MAIN, A, B etc (si elles n’ont pas été définies par l’action).

10.3.2 Astuces utiles

Lorsque vous définissez une réponse personnalisée, il peut être utile de récupérer certaines valeurs de votre applica-
tion, comme
– le theme : $GLOBALS[’gJConfig’]->theme
– les paramètres de la requête : $GLOBALS[’gJCoord’]->request->getParam(..)
Ci-dessous un exemple

public function __construct() {


parent::__construct();
$theme = $GLOBALS[’gJConfig’]->urlengine[’basePath’].’themes/’.$GLOBALS[’ ←-
gJConfig’]->theme.’/’ ;
$this->addCSSLink($theme.’css/screen.css’);
}

protected function _commonProcess(){

$this->title .= ($this->title !=’’?’ - ’:’’).’ My App’;

$param = $GLOBALS[’gJCoord’]->request->getParam(’paramSommaire’)

// toutes les pages auront une zone de login affichée


$this->body->assignZone("A", "auth~login", array( ’paramSommaire’ => ←-
$param ) );
Jelix 1.0.6
Guide du développeur
65 / 225

// et au cas où rien n’est défini pour B,C,D et MAIN, on met du contenu


// par défaut
$this->body->assignIfNone(’B’,’’);
$this->body->assignIfNone(’C’,’’);
$this->body->assignIfNone(’D’,’’);
$this->body->assignIfNone(’MAIN’,’<p>No content</p>’);

// on indique les autres variables


$this->body->assign(’date’, date(’Y-m-d’));
}

10.3.3 Définir plusieurs réponses

Notez que vous pouvez définir plusieurs réponses html, dans le cas où votre site comporte plusieurs pages type. Par
exemple :
[responses]
html=myHtmlResponse
html2=myOtherHtmlResponse
adm=adminHtmlresponse

Il suffira alors dans les actions d’indiquer le bon code pour indiquer le type de réponse :
$rep = $this->getResponse(’html’);
// ou
$rep = $this->getResponse(’html2’);
// ou
$rep = $this->getResponse(’adm’);

10.3.4 Utiliser ponctuellement une réponse d’origine

Si dans une action, vous voulez absolument utiliser la classe d’origine fourni par Jelix, et non celle qui redéfinit un
type de réponse, vous pouvez alors l’indiquer en indiquant true en deuxième paramètre de getResponse :
$rep = $this->getResponse(’html’, true);

$rep contiendra un objet de type jResponseHtml, et non myHtmlResponse.

10.4 Utilisation de zones

Il se peut qu’un ensemble de page possède une ou plusieurs zones identiques, sans que cela soit général à tout le site.
Vous pouvez alors créer des zones.
Jelix 1.0.6
Guide du développeur
66 / 225

Troisième partie

Composants de jelix
Jelix 1.0.6
Guide du développeur
67 / 225

Cette partie vous permet de découvrir tout les composants que Jelix vous offre, en dehors des objets spécifiques à la
structure d’un projet et au modèle MVC.
Voici donc comment utiliser les templates, accéder aux bases de données, réaliser des formulaires, internationaliser
votre application etc.
Jelix 1.0.6
Guide du développeur
68 / 225

Chapitre 11

jTpl : le moteur de templates

Jelix inclu son propre moteur de template jTpl. Les templates sont des fichiers portant l’extension ".tpl" et se trouvant
dans le répertoire "templates" des modules.

11.1 L’objet jTpl

L’objet jTpl sert à générer le contenu indiqué dans un fichier template, à partir des données que vous lui fournissez,
et en suivant les instructions contenues dans le template.
Les objets jResponse ou jZone instancie pour vous un objet jTpl. Par exemple, la propriété body de l’objet jRespon-
seHtml est un objet jTpl, de même que la propriété _tpl de jZone.
Dans d’autres circonstances, vous aurez à faire :
$tpl = new jTpl();

Voici les méthodes les plus importantes à connaître.

11.1.1 assign

$tpl->assign($nom, $valeur);

Cette méthode vous permet de créer une variable de template. Une variable de template n’est accessible qu’au niveau
du template. C’est avec cette méthode que vous pouvez donc passer des données (valeurs statiques, objets, itérateurs,
etc..) au template pour vous en servir à générer du contenu.
Vous pouvez également créer ou modifier une variable directement dans le fichier tpl en utilisant.
{assign $nom = $valeur}

– *important** : le nom d’une variable de template doit respecter les conventions de nommage des noms de variables
PHP. Par exemple, le nom ne doit pas contenir de tiret ou d’autres signes de ponctuations. Il ne doit contenir que
des lettres avec éventuellement des chiffres et le caractère souligné (_).

11.1.2 assignIfNone

Idem que assign, mais la valeur est assignée à la variable uniquement si celle-ci n’existe pas.
Jelix 1.0.6
Guide du développeur
69 / 225

11.1.3 assignZone

$tpl->assignZone($name, $zoneSelector, $params);

Le paramètre params est facultatif. Cette méthode est un raccourci de :


$tpl->assign($name, jZone::get($zoneSelector, $params));

11.1.4 assignZoneIfNone

Idem que assignZone, mais la valeur est assignée à la variable uniquement si celle-ci n’existe pas.

11.1.5 get

Si vous voulez récupérer la valeur d’une variable de template déjà initialisée, vous pouvez utiliser cette méthode.
$value = $tpl->get(’foo’);

11.1.6 Récupération du contenu

Une fois que les variables sont initialisées, vous pouvez appeler la méthode fetch pour générer le contenu du template
et le récupérer. Vous donnerez à cette méthode le selecteur du fichier de template.
$contenu = $tpl->fetch(’mymodule~mytemplate’);

L’appel de cette méthode n’est indispensable que dans le cas où vous avez instancier vous même l’objet jTpl.
Il existe une autre méthode, mais que vous n’appelerez jamais puisque les objets jResponse le font à votre place :
display.
$tpl->display(’mymodule~mytemplate’);

Le contenu du template est évalué et affiché directement.

11.2 Les fichiers templates

Un fichier de template contient du HTML, du XUL ou ce que vous voulez qui soit en rapport avec le type de la
réponse. Il contient aussi des instructions pour incorporer des valeurs que vous aurez fournies, des instructions pour
générer répétitivement des portions de HTML, XUL etc.
La syntaxe utilisée dans jTpl est à mi chemin entre celle utilisée dans le moteur de template Smarty, et la syntaxe
PHP. Le but étant d’avoir des templates suffisamment lisibles, facile à modifier en n’imposant pas une syntaxe trop
éloignée de PHP, tout en proposant des facilités que ne possède pas PHP et propres à Jelix.
Il faut avoir en tête que la plupart des templates que vous ferez ne doivent pas contenir de fichiers entiers. En
particulier, pour les réponses HTML, vos templates ne doivent contenir que ce qui se trouve entre les balises <body>
et </body> de votre page, le reste étant généré automatiquement par jResponseHtml.
Jelix 1.0.6
Guide du développeur
70 / 225

11.2.1 Syntaxe des instructions

Les instructions jTpl sont spécifiées entre accolade : {instruction....}.


Si vous voulez inclure des accolades dans le source, sans que ce soit interprété par jTpl, vous pouvez utiliser {ldelim}
pour {, et {rdelim} pour }. Si vous avez un bloc contenant plusieurs accolades (comme du code javascript), vous
pouvez aussi utiliser l’alternative avec {literal} :
<script type="text/javascript">
{literal}
for(i=0;i<max;i++) {
if(foo){ ...}
}
{/literal}
</script>

Si vous voulez mettre des commentaires qui ne seront pas inclus dans le contenu généré, utilisez {*...*}
<p>bla bla</p>
{* ceci est un commentaire *}

11.2.2 Expressions

Une expression jTpl est identique à une expression PHP et renvoie, comme dans PHP, une valeur. Vous pouvez
utiliser les opérateurs PHP classiques, les objets, etc...
On peut utiliser les variables de templates qu’on a passées à jTpl, comme des variables classiques en PHP :
$nom_variable_de_template

Une expression peut contenir aussi des sélecteurs de locale, en utilisant une syntaxe spécifique à jTpl. Ce type de
sélecteur doit être placé entre @. jTpl ira chercher la chaîne correspondante dans la langue courante :
@mon_module~cle.chaine.localisee@."fooo bar"

La chaîne correspondant à mon_module~cle.chaine.localisee sera récupérée et concaténée à "fooo


bar".
À l’intérieur du nom de la clé, on peut indiquer un nom de variable de template. Cela permet ainsi de construire un
nom de clé dynamiquement.
@mon_module~cle.chaine.$nom_variable_template.autre@

si $nom_variable_template vaut "foo", alors la clé sera "mon_module~cle.chaine.foo.autre".

11.2.3 Affichage d’une expression, d’une variable

Il faut mettre l’expression entre accolade. Elle doit commencer par un nom de variable ou par un sélecteur de locale :
{$mavariable}
{$mavariable * 3}
{$mavariable." - ".@mod~message.ok@}
{@modul~une.cle.de.locale@."-".$uneAutreVariable}
{@modul~une.cle.$dynamique@."-".$uneAutreVariable}

Ceci est équivalent en php à


Jelix 1.0.6
Guide du développeur
71 / 225

<?php echo $mavariable; ?>


<?php echo $mavariable * 3; ?>
<?php echo $mavariable." - ".jLocale::get("mod~message.ok"); ?>
<?php echo jLocale::get("modul~une.cle.de.locale")."-".$uneAutreVariable; ?>
<?php echo jLocale::get("modul~une.cle.".$dynamique)."-".$uneAutreVariable; ?>

11.2.4 Constantes prédéfinies

Pour apporter une certaine facilité, des variables de templates prédéfinies ont été ajoutées :
– $j_basepath : contient le chemin url du répertoire de l’application (paramètre de configuration basePath)
– $j_jelixwww : contient le chemin url vers le contenu du répertoire jelix-www (paramètre de configuration je-
lixWWWPath)
– $j_themepath : contient le chemin url vers le répertoire du thème courant
– $j_datenow : date courante (aaaa-mm-jj)
– $j_timenow : heure courante (hh :mm :ss)

11.2.5 Modificateurs

Un modificateur est en fait une fonction qui va modifier le contenu qui va être affiché. Cela fonctionne comme dans
smarty. On peut mettre plusieurs modificateurs à la suite :
{$unevariable|upper}
{$unevariable|upper|escxml}
{$uneUrl|escurl}

Ceci est en fait équivalent à :


<?php echo strtoupper($unevariable);?>
<?php echo htmlspecialchars(strtoupper($unevariable));?>
<?php echo rawurlencode($uneUrl);?>

Les modificateurs indiqués en exemple sont de simples alias à des fonctions existantes, mais vous pouvez créer vos
propres modificateurs, pouvant accepter plusieurs arguments.
Les modificateurs existants et leur équivalent php :
– upper (strtoupper)
– lower (strtolower)
– escxml (htmlspecialchars)
– strip_tags (strip_tags)
– escurl (rawurlencode)
– capitalize (ucwords)
D’autres sont fournis. Voir la liste sur la référence API.

modificateur avec paramètres

Il peut y avoir des modificateurs qui acceptent des paramètres. Vous devez mettre ceux-ci, séparés par des virgules
(,) , après le nom du modificateur et deux-points ( :).
Exemple : ici le modificateur jdatetime, prenant deux paramètres de type chaîne :
<p>la date est {$myDate|jdatetime:’db_date’,’timestamp’}.</p>
Jelix 1.0.6
Guide du développeur
72 / 225

11.3 Les structures de contrôle

Elles sont équivalentes à celle en PHP. Voici celles qui sont pour le moment implémentées :

11.3.1 if, else, elseif

{if condition_1}
// code ici
{elseif condition_2}
// code ici
{else}
// code ici
{/if}

Note : les parenthèses encadrant la condition ne sont pas obligatoires.

11.3.2 while

{while condition}
// code ici
{/while}

Note : les parenthèses encadrant la condition ne sont pas obligatoires.

11.3.3 foreach

{foreach expression}
// code ici
{/foreach}

Note : il ne faut pas entourer l’expression par des parenthèses.

11.3.4 for

{for expression}
// code ici
{/for}

L’expression est bien sûr semblable à celle du "for" en PHP. Cependant, il ne faut pas entourer l’expression par des
parenthèses.
Jelix 1.0.6
Guide du développeur
73 / 225

11.4 Fonctions jTpl

Ce sont des fonctions classiques mais appelables uniquement dans un template. Certaines sont disponibles en stan-
dard et vous pouvez en réaliser en créant un plugin de template. Leur syntaxe est :

{nom_fonction paramètres}

Les paramètres sont des expressions jTpl, donc similaires aux expressions PHP. Cependant, contrairement en PHP,
il ne faut pas entourer les paramètres par des parenthèses.
Sachez que les fonctions, et en général la plupart des plugins de templates, sont attribués à un type de réponse
particulier. Donc il existe des fonctions utilisables dans des templates pour les réponses HTML, mais pas dans les
templates pour les réponses Text par exemple.

11.5 informations meta

Il existe une balise assez spéciale : {meta}. Elle n’influence pas l’interprétation du template, ne génère aucun contenu,
mais permet de fournir des informations sur le template qui pourraient être réutilisées par un programme utilisant le
template.
{meta nom expression}
Exemple :

{meta auteur ’laurent’}

On peut en mettre plusieurs bien sûr. Ces informations sont récupérables via la méthode meta() de l’objet jTpl :
$tpl = new jTpl();

$metas = $tpl->meta(’le_fichier_template’);

echo $metas[’auteur’]; // affiche ’laurent’

11.6 Informations meta avançées

Des informations meta peuvent être traitées automatiquement via un plugin de template. Par exemple, il existe un
plugin de meta permettant d’indiquer des informations pour une réponse HTML (feuille de style CSS, script JS, etc...).
Leur syntaxe est :

{meta_nom_plugin nom expression}

Exemple :

{meta_html css ’/styles/my.css’}


{meta_html js ’fooscript.js’}
{meta_html bodyattr array(’onload’=>’alert("charge")’)}

Un plugin similaire existe pour XUL, et bien sûr vous pouvez réaliser le votre.
Jelix 1.0.6
Guide du développeur
74 / 225

11.7 Surcharge de template

Chaque module défini des templates qui lui sont propres, mais pour éviter d’avoir à retravailler sur les templates
originaux du module lorsque ce dernier est réutilisé dans une autre application, il est possible d’appliquer d’autres
templates afin de produire un nouvel affichage, sans toucher au contrôleur.
Pour cela Jelix utilise un système de thème, le thème par défaut étant stocké dans /var/themes/default, il est possible
d’ajouter d’autres thèmes en ajoutant simplement des répertoires dans /var/themes, par exemple /var/themes/mon_theme.
Ainsi /var/themes/mon_theme/mon_module/mon_template.tpl redéfini le template mon_template du module mon_module
pour le thème mon_theme.
Pour plus de détails, voir la page sur les thèmes.

11.8 En coulisse

Les templates jTpl sont "compilés" sous forme de fichiers purs PHP, et stockés dans un cache pour améliorer les per-
formances. Vous pouvez donc voir l’équivalence d’un de vos fichiers templates dans temp/votre_application/compiled/templa
ou pour les templates redefinis dans les themes : temp/votre_application/compiled/templates/themes/nom_theme/nom_modul
Vous pouvez créer aussi des plugins de templates, pour ajouter vos propres "tags" dans la syntaxe jtpl. Voir tpl.
Jelix 1.0.6
Guide du développeur
75 / 225

Chapitre 12

jZone : découper vos pages en zones

12.1 Principes d’une zone

Les zones dans Jelix représentent des morceaux de la réponse finale. En d’autre termes, elles sont destinées à gérer
et générer le contenu d’une portion de l’écran, de la page web. Une page web est donc composée essentiellement de
zones.
L’intérêt d’utiliser les zones est de :
– pouvoir réutiliser une zone dans des pages différentes : une zone est en théorie indépendante du contexte : elle fait
elle même appel aux classes métiers et possède son propre template.
– avoir une génération de contenu paramétrable : les zones acceptent des paramètres.
– pouvoir générer plus rapidement les pages, en activant la mise en cache des zones : seules les zones dont les
paramètres changent (la zone principale en général) sont régénérées (ou celles dont on aura effacé le cache).
– au passage, alléger le code des contrôleurs.

12.2 Utilisation des zones

12.2.1 Création

Une zone est déclarée via une classe héritant de jZone. Le nom de cette classe est le nom de la zone suivit du mot
"Zone"
class testZone extends jZone {

Elle doit être stockée dans un fichier nom_de_la_zone.zone.php, dans le répertoire zones du module. Ici donc, il
s’agit du fichier zones/test.zone.php.
Par défaut, un objet jZone instancie un moteur de template.

Utilisation sans template

Si vous ne voulez pas utiliser de template pour votre zone, vous devez surcharger la méthode _createContent, qui
doit renvoyer le contenu de la zone sous forme de chaine. Vous ne devez pas faire d’echo ou de print !
Jelix 1.0.6
Guide du développeur
76 / 225

class testZone extends jZone {

protected function _createContent(){


return "<p>Ceci est le contenu d’une zone</p>";
}
}

Utilisation avec template

La plupart du temps, vous utiliserez toutefois un template. Vous devez indiquer dans la propriété $_tplname le
template que vous utilisez (c’est un sélecteur), et surcharger la méthode _prepareTpl(). Cette méthode est, comme son
nom l’indique, chargée d’initialiser l’objet jTpl instancié automatiquement par jZone et stocké dans la propriété _tpl.
class testZone extends jZone {

protected $_tplname=’template_test’;

protected function _prepareTpl(){


$this->_tpl->assign(’foo’,’bar’);
}
}

Et le template (stocké dans templates/template_test.tpl) :

<p>Ceci est un template. Et foo vaut {$foo}.</p>

12.3 Appel

Il y a plusieurs façons de récupérer le contenu d’une zone en fonction de ce que l’on veut faire.
Si on veut récupérer simplement son contenu (dans un contrôleur) on fait :
$contenu = jZone::get(’test’); // ou ’leModule~test’...

Cependant, il arrive très souvent qu’il s’agisse d’affecter le contenu de la zone à une variable du template principal,
lorsque la réponse possède un template principal (ce qui est le cas des réponses HTML qui possèdent un objet jTpl
dans sa propriété body). Dans le contrôleur, on pourra donc utiliser la méthode assignZone de jTpl :
$rep = $this->getResponse(’html’);
$rep->title = ’page de test’;
$rep->bodyTpl = ’testapp~main’;
$rep->body->assignZone(’MAIN’, ’test’);

test correspondant au nom du fichier test.zone.php MAIN correspondant à la variable de template {$MAIN}
Autre solution, on peut avoir dans un template, un appel de zone direct :
<div id="menu"> {zone ’leModule~test’} </div>
Jelix 1.0.6
Guide du développeur
77 / 225

12.3.1 Appel avec des paramètres

Il est possible de faire passer des paramètres à une zone. Pour cela, on procède de la manière suivante :
Appel depuis un contrôleur :
$rep = $this->getResponse(’html’);
$rep->title = ’page de test’;
$rep->bodyTpl = ’testapp~main’;
$rep->body->assignZone(’MAIN’, ’test’, array(’foo’=>’bar’));

Et pour récupérer la variable dans la zone, on utilise la méthode getParam() :


class testZone extends jZone {

protected $_tplname=’template_test’;

protected function _prepareTpl(){


$foo = $this->getParam(’foo’);
$foo = strtoupper($foo);
$this->_tpl->assign(’foo’, $foo);
}
}

Dans cet exemple on a fait passer la variable ’foo’ avec pour valeur ’bar’ en paramètre de la zone. On a récupéré
la variable ’foo’ dans la zone pour effectuer un traitement dessus (ici, mise en majuscule) et on a affecté ’foo’ au
template de la zone.
À noter que Jelix affecte automatiquement les variables passées en paramètres de la zone au template de zone si il
existe. Vous pouvez vous passer d’écrire :
protected function _prepareTpl(){
$this->_tpl->assign(’foo’, $this->getParam(’foo’));
}

Si vous utilisez le plugin de template zone, le passage des paramètres à la zone s’effectue de cette manière :
<div id="menu"> {zone ’leModule~test’, array(’foo’=>’bar’)} </div>

12.4 Utilisation du cache

Il est possible de mettre le contenu généré dans un cache. Et il peut y avoir un cache pour chaque valeur des para-
mètres de la zone.

12.4.1 Activation du cache

Par défaut, une zone ne gère pas de cache : il faut donc l’activer dans votre classe, via la propriété _useCache en
la mettant à true :
class testZone extends jZone {

protected $_useCache = true;

}
Jelix 1.0.6
Guide du développeur
78 / 225

Le contenu de la zone sera ainsi mis dans un fichier de cache. Si la zone a des paramètres, un cache sera crée pour
à chaque valeur différente des paramètres. Ainsi, si vous avez un paramètre ’id_article’, un cache sera crée à chaque
fois que la zone sera appelée avec une valeur de id_article différente.
– *ATTENTION** : un cache se matérialise par un fichier dans le répertoire temporaire de l’application. Si vous
avez des milliers d’articles, cela peut engendrer autant de fichiers dans votre répertoire temporaire. Il faut donc
éviter dans un cas comme celui-là, d’activer le cache si votre hébergeur vous limite en nombre de fichiers par
exemple.
Utilisez donc le cache à bon escient. Par exemple, pour une application fréquentée moyennement (un même article
lu seulement quelque fois par jour), il n’est pas forcément nécessaire d’activer le cache. À vous de juger...
(note : il était documenté auparavant l’utilisation d’une propriété _cacheParams. Cette propriété n’a en fait jamais
été utilisé dans jZone, donc n’a jamais servi à rien...)

12.4.2 Rafraîchissement du cache

Il est nécessaire de régénérer le cache quand les informations contenues sont obsolètes. Cette régénération peut se
faire automatiquement régulièrement (toutes les n secondes), ou alors être forcée manuellement.
Vous utiliserez l’une ou l’autre des méthodes selon les cas. La deuxième méthode est moins gourmande en ressource
puisque le cache ne se régénère uniquement en temps voulu. L’inconvénient c’est qu’il faut explicitement effacer le
cache dans vos classes métier. La première méthode évite ce travail, mais consomme plus de ressources, et le contenu
de la zone n’est pas à jour pendant le délai indiqué. À réserver donc pour afficher des informations non vitales, dont
la "fraîcheur" n’a pas vraiment d’importance.

Automatique

Pour un rafraîchissement automatique, il suffit d’indiquer dans la propriété _cacheTimeout le délai d’invalidité
du cache, en secondes :
class testZone extends jZone {

protected $_useCache = true;

protected $_cacheTimeout = 60;


}

Ici le cache sera régénéré toutes les 60 secondes. Si vous mettez 0, il n’y aura pas de rafraîchissement automatique.

Forcé

La suppression "manuelle" du cache se fait via les méthodes statiques clear et clearAll.
Par exemple, dans la classe métier de votre article, au moment de modifier l’article (en base de données par exemple)
ou de le supprimer, vous allez appeler jZone pour qu’il supprime le cache correspondant, afin qu’il soit régénéré au
prochain affichage. Bien sûr, il faut indiquer les valeurs des paramètres qui identifient le cache. Dans notre exemple
donc, id_article.
jZone::clear(’mymodule~article’, array(’id_article’=>546));

Si vous voulez effacer tous les caches d’une même zone, vous pouvez appeler clearAll :
jZone::clearAll(’mymodule~article’);

Et si vous voulez effacer tous les caches de toutes les zones :


jZone::clearAll();
Jelix 1.0.6
Guide du développeur
79 / 225

12.5 Empêcher ponctuellement la mise en cache

Il faut noter que les méthodes _createContent et _prepareTpl (que vous pouvez surcharger), ne sont appelées que
lorsque le cache doit être régénéré.
Il se peut que pour une raison ou pour une autre (en fonction de la valeur d’un certain paramètre par exemple), vous
ne vouliez pas que parfois le résultat de la zone soit mis en cache.
Il suffit alors, dans _createContent ou _prepareTpl, de mettre la propriété _cancelCache à true

protected function _prepareTpl(


// ....
$this->_cancelCache=true;
//...
}

12.6 Paramètres automatiques

L’affichage d’une zone peut dépendre de paramètres donnés explicitement, mais aussi de paramètres "externe" im-
plicites. C’est le cas par exemple pour une zone qui affiche la version d’un article en fonction de la langue configurée
dans l’appli. On peut bien sûr passer à chaque appel de zone le code langue, mais ce n’est pas forcément pratique.
On pourrait ne pas avoir à l’indiquer dans les paramètres, et le récupérer soit même dans _prepareTpl/_createContent,
mais alors il n’est pas possible que cela devienne un critère discriminant pour le système de cache si vous l’utilisez.
La solution est de surcharger le constructeur, et d’initialiser ce paramètre :
class articleZone extends jZone {

protected $_useCache = true;

public function __construct($params=array()){


$params[’lang’] = $GLOBALS[’gJConfig’]->locale;
parent::__construct($params);
}

}
Jelix 1.0.6
Guide du développeur
80 / 225

Chapitre 13

jDao : mapping objet relationnel

jDao permet de générer des objets PHP qui opèrent sur des tables précises de base de données. La génération de ces
objets inclus la génération des requêtes SQL qui correspondent à ces opérations.
Pour ce faire, jDao se base sur un fichier XML que vous devez fournir. Ce fichier permet de s’affranchir de l’écriture
fastidieuse des requêtes SQL, permet de tenir compte des problématiques du genre SQL injection : les objets générés
s’occupent de tout. Le fichier XML peut être généré par un outil de développement, comme par exemple l’une des
commandes fournies avec le script Jelix.
À partir d’un fichier XML de ce type, jDAO fourni donc deux objets, un objet "record" et un objet "factory", selon
le pattern DAO.
Un objet record représente un enregistrement : ses propriétés correspondent avec les champs d’une ou plusieurs
tables.
Un objet factory fourni un certain nombre de méthodes permettant de créer un record, de le sauvegarder, de le détruire
ou de récupérer des ensembles d’objets record.

13.1 Fichier DAO de base

Pour utiliser jDao, il faut d’abord décrire dans un fichier XML le mapping objet-relationnel, c’est à dire indiquer
dans ce fichier la correspondance entre les propriétés de l’objet DAO et les champs d’une ou plusieurs tables

13.1.1 Création automatique

Le fichier d’un DAO peut être généré par le script jelix en ligne de commande, à partir d’une table de base de donnée
existante.
php jelix.php createdao nom_module nom_dao nom_table

Par exemple, si je veux créer dans le module "myshop", un DAO "product" qui sera basé sur la table "shop_product",
vous taperez donc :
php jelix.php createdao myshop product shop_product

Dans le répertoire daos du module myshop vous allez donc avoir un fichier XML product.dao.xml qui va contenir la
description du mapping.
Bien que la génération automatique permet de gagner du temps, il faut souvent retoucher le fichier pour que le
mapping corresponde mieux à ce que l’on veut faire, le générateur ne pouvant tout deviner. Voyez alors la suite pour
le compléter, ou en créer un à la main.
Jelix 1.0.6
Guide du développeur
81 / 225

13.1.2 Détails sur le format XML

La structure d’un fichier DAO ressemble à cela :


<dao xmlns="http://jelix.org/ns/dao/1.0">
<datasources>
section datasources
</datasources>
<record>
section properties
</record>
<factory>
section methodes
</factory>
</dao>

Il y a trois sections, sachant que la section "factory" (ou "methodes") est facultative et est décrite dans une autre page
dédiée.
– datasources : indique les tables sur lequel reposera l’objet.
– record : indique la correspondance entre les propriétés de l’objet et les champs des tables et définit donc les
propriétés qu’il y aura sur l’objet record.

13.1.3 Correspondance simple

Déclaration de la table

On appelle correspondance simple, une correspondance où un record = une table. Pour déclarer la table sur laquelle
reposera le DAO, on utilise la balise primarytable, avec les attributs suivants :
– name : alias donné à la table et qui sera utilisé dans les requêtes
– realname (facultatif) : nom réel de la table dans la base de données. Si cet attribut n’est pas précisé, il prend la
même valeur que l’attribut name. Dans ce cas name doit être le nom réel de la table.
– primarykey indique la clé primaire. Vous pouvez indiquer plusieurs clés en les séparant par un espace ou une
virgule.
<datasources>
<primarytable name="p" realname="products" primarykey="id_product" />
</datasources>

On déclare ici que le record sera basé sur la table "products", qui a pour alias "p", et dont la clé primaire est
"id_product".
Il n’y a toujours qu’une seule table "primaire" dans un DAO (donc une seule balise <primarytable>). Vous verrez
que l’on peut indiquer des tables annexes (étrangères) plus loin.
Ensuite, il faut déclarer la correspondance propriété - champs.

Déclaration des propriétés

La section record déclare les propriétés d’un objet record (enregistrement). Chaque propriété correspond à l’un des
champs de la table primaire, ou l’un de ceux des tables étrangères comme vous le verrez plus loin. Bien sûr, vous
n’êtes pas obligés de déclarer une propriété pour tous les champs existants. On peut ainsi faire plusieurs DAO qui
travaillent sur une même table mais qui sont destinés à des usages différents. Par exemple faire un DAO spécifique
pour récupérer des listes légères d’enregistrement (on ne déclarera que les propriétés essentielles), et un autre pour les
gérer de manière complète (on y indiquera tous les champs).
La section record doit donc contenir une ou plusieurs balises <property> :
Jelix 1.0.6
Guide du développeur
82 / 225

<property
name="nom simplifié"
fieldname="nom du champ"
datatype="" required="true/false" minlength="" maxlength="" regexp=""
sequence="nom de la sequence"
updatepattern="" insertpattern="" selectpattern=""
default=""
/>

L’attribut name est le nom de la propriété de l’objet.


L’attribut fieldname est le nom du champ qui correspond. Si name et fieldname sont égaux, on peut omettre fieldname.
Les attributs datatype, required, minlength, maxlength, et regexp sont des contraintes. Cela permet par la suite d’ap-
peler la méthode check() sur un record pour vérifier les valeurs des propriétés (avant son stockage par exemple).
L’attribut default permet d’indiquer une valeur par défaut.
L’attribut datatype peut prendre les valeurs :
– string
– int/integer
– autoincrement
– double/float
– numeric/bigautoincrement
– date
– time
– datetime
– boolean
Sur certaines bases, on peut associer une séquence à un champ. L’attribut sequence indique son nom.
Les attributs updatepattern, insertpattern et selectpattern permettent d’indiquer un "motif" à appliquer lors de la
mise à jour, l’insertion ou la lecture de la valeur du champ dans la table. Ce motif doit en fait être une expression
SQL, contenant éventuellement la chaîne "%s" qui sera remplacée par la valeur ou le nom du champ. Par défaut leurs
valeurs vaut "%s". Si on indique une valeur vide, cela correspond à une opération nulle (le champ n’est pas lu, inséré
ou mis à jour).

Exemple 1

Pour un champ qui contient une date de mise à jour, on pourra indiquer :
<property name="date_update" datatype="datetime" insertpattern="NOW()" ←-
updatepattern="NOW()" />

Ainsi chaque fois qu’un INSERT ou un UPDATE sera fait, la valeur insérée sera la date du jour (et non celle que l’on
aurait indiquée dans la propriété date_update du record).

Exemple 2

On peut aussi avoir une propriété qui ne correspond pas directement à un champ, mais qui soit le résultat d’une
expression SQL. Dans ce cas, il faut désactiver l’insertion et la mise à jour.
<property name="identite" datatype="string" selectpattern="CONCAT(nom, ’ ’, ←-
prenom)" insertpattern="" updatepattern="" />

Attention, en ce qui concerne l’expression de selectPattern :


Jelix 1.0.6
Guide du développeur
83 / 225

– l’expression doit utiliser des champs d’une même table. Si le dao est basé sur plusieurs tables (ex : A et B, voir
section suivante), il n’est pas possible que l’expression utilise à la fois des champs de la table A et de la table B
– si l’expression utilise des champs d’une table B qui ne soit pas la table principale, la propriété doit être attribué à
cette table B, et non à la table principale. Ce qui veut dire que la propriété doit avoir un attribut table ayant pour
valeur le nom/alias de cette table B.

13.1.4 Correspondance avec plusieurs tables

On peut déclarer une table principale, mais aussi des tables annexes qui seraient liées à la table principale par des
jointures. Il est utile, lorsque l’on veut récupérer un enregistrement, de récupérer en même temps des informations de
tables annexes. Par exemple, si on veut récupérer un produit de la table products, et en même temps le libellé de sa
catégorie qui se trouve dans une table "category", on déclarera aussi la table "category". À noter que vous ne pourrez
modifier que les données issues de la table principale quand vous voudrez mettre à jour un enregistrement.
Pour déclarer de telles tables étrangères, qui en toute logique sont liées à la table principale par des clés étrangères,
il faut utiliser :
– foreigntable pour indiquer une table étrangère liée par une jointure normale.
– optionalforeigntable pour indiquer une table étrangère liée par une jointure externe.

Exemple

<primarytable name="p" realname="products" primarykey="id_product" />


<foreigntable name="cat" realname="categories" primarykey="id_cat" onforeignkey ←-
="id_cat" />
<optionalforeigntable name="man" realname="manufacturers" primarykey="id" ←-
onforeignkey="id_manufacturer" />

Comme pour la balise primarytable, il y a les attributs name, realname et primarykey. Il y a par contre un attribut
supplémentaire, onforeignkey, qui indique le nom du champ dans la table primaire, qui est la clé étrangère sur la table
en question. Ainsi, avec l’exemple ci-dessus, jDao générera pour les requêtes de type SELECT les clauses FROM et
WHERE suivantes :
FROM products as p left join manufacturers as man on (p.id_manufacturer = man.id) ←-
, categories as cat
WHERE cat.id_cat = p.id_cat

Indiquer des tables annexes n’a de sens que si vous voulez avoir une ou plusieurs propriétés correspondantes à leurs
champs. Vous ajouterez donc autant de balise <property> que vous voudrez. La seule différence est qu’il faut ajouter
un attribut table qui indique l’alias de la table dans lequel se trouve le champ.
<property
name="libelle_categorie"
fieldname="label"
table="cat"
/>

Dans la propriété libelle_categorie du record, se trouvera la valeur du champ label de la table categories ("cat" étant
l’alias de cette table, comme il a été défini plus haut dans la balise foreigntable ).

13.2 Instanciation et utilisation d’une factory et d’un record DAO

Vous avez vu comment décrire dans un fichier XML un DAO (voir fichier_de_base). Ce fichier, vous devez le stocker
dans un répertoire "daos/" d’un module et le nommer comme ceci : nom.dao.xml. nom est le nom de votre DAO.
Souvenez vous qu’en fait vous définissez deux objets :
Jelix 1.0.6
Guide du développeur
84 / 225

– un objet DAO qui est une factory : elle permet de récupérer, insérer, modifier, effacer un ou plusieurs enregistre-
ments. Elle propose des méthodes de base, mais contient aussi les méthodes dont vous avez décris les propriétés
dans le fichier XML
– un objet record DAO qui représente un enregistrement et dont vous avez décris les propriétés dans le fichier XML

13.2.1 Récupérer la factory

Pour récupérer ces objets il faut passer par l’objet jDao qui propose diverses méthodes statiques :
– get : permet d’obtenir une factory. renvoi toujours la même instance (utilise un singleton)
– create : permet d’obtenir une nouvelle instance d’une factory. rarement utile.
– createRecord : permet d’obtenir un objet DAO record vide.
– createConditions : permet d’obtenir un objet jDAOConditions qui permet d’indiquer des conditions de sélection
pour récupérer un ensemble d’objet record.
get, create et createRecord prennent tous en argument un sélecteur de fichier DAO et un deuxième paramètre facultatif
qui est le nom du profil jDb à utiliser (si paramètre absent, il prendra celui par défaut).
Si le profil jDb utilisé spécifie un préfixe de table, alors toutes les tables indiquées dans le DAO verront leur nom
préfixé par la valeur de ce paramètre.
En admettant qu’il y ait un fichier DAO foo.dao.xml dans le module bar :
$maDao = jDao::get("bar~foo");
// ou si cette ligne de code est dans un fichier du module bar :
$maDao = jDao::get("foo");

$monRecord = jDao::createRecord("foo");

$maDao contient une factory de foo, et $monRecord un enregistrement vide de type foo.

13.2.2 Récupérer des records

Une factory DAO propose par défaut deux méthodes :


– findAll : pour récupérer tous les enregistrements
– get : pour récuperer un enregistrement en indiquant sa clé

// instanciation de la factory
$maFactory = jDao::get("foo");

// récupération d’une liste complète de records de type foo


$liste = $maFactory->findAll();

// récupération d’un record dont le contenu correspond


// à l’enregistrement ayant pour identifiant 3
$baz = $maFactory->get(3);

Vous pouvez réaliser d’autres méthodes de récupération, en les spécifiant dans le fichier XML (voir DAO avancés).

13.2.3 Récupérer des records selon critères

Les factory DAO mettent à disposition la méthode findBy, qui s’utilise en lui passant un objet jDaoConditions :
Jelix 1.0.6
Guide du développeur
85 / 225

$conditions = jDao::createConditions();
$conditions->addCondition(’libelle’,’=’,$un_nom);
$conditions->addCondition(’status’,’=’,5);

$liste = $maFactory->findBy($conditions);

La méthode addCondition prend en paramètre un nom de propriété, un opérateur (SQL), et une valeur. findBy renvoi
la liste des records qui correspondent aux critères indiqués. Vous pouvez aussi indiquer un ordre de sélection, et
regrouper divers critères ensemble :
$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 : (int $limitOffset, int
$limitCount) Par exemple pour récupérer les 15 premiers enregistrements :
$liste = $maFactory->findBy($conditions, 0, 15);

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 faîtes 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. Cela améliore les performances globales.
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.
Il arrive souvent par exemple de redéfinir la méthode findAll en XML, pour indiquer un ordre de récupération...

13.2.4 Créer, modifier, effacer un enregistrement

Les méthodes insert, update, et delete de la factory sont faites pour ça. Aux deux premières, vous indiquez un record.
Pour delete, vous indiquez les clés de l’enregistrement.

Création

Il faut récupérer un nouvel objet record, le remplir, et ensuite appeler la méthode insert
// instanciation de la factory
$maFactory = jDao::get("foo");

// creation d’un record correspondant au dao foo


$record = jDao::createRecord("foo");
Jelix 1.0.6
Guide du développeur
86 / 225

// on remplie le record
$record->champ1 = "hello";
$record->champ2 = "...";

// on le sauvegarde dans la base


$maFactory->insert($record);

Si il y a des champs de type autoincrement, les propriétés correspondantes dans $record seront mises à jour avec la
nouvelle valeur.

Modification

Le processus est le suivant : on récupère un objet record, on modifie ses propriétés, et on appelle la méthode update :
// instanciation de la factory
$maFactory = jDao::get("foo");

// récupération du record dont l’identifiant est 3


$record = $maFactory->get(3);

// on modifie le record
$record->champ1 = "hello";
$record->champ2 = "...";

// on le sauvegarde dans la base


$maFactory->update($record);

Destruction

Il suffit d’appeler la méthode delete en donnant l’id du record à détruire


// instanciation de la factory
$maFactory = jDao::get("foo");

// destruction du record dont l’identifiant est 3


$maFactory->delete(3);

13.3 Ajouter des méthodes en XML

Une factory générée par jDao contient par défaut un certain nombre de méthodes (find, findAll, get, insert, etc...)
comme décrit sur la page sur l’utilisation des daos. Cependant, elles ne sont pas forcément suffisantes, et l’on a
souvent besoin de faire des sélections, des mises à jour ou des suppressions particulières.
La section <factory> permet de définir des méthodes supplémentaires à générer, chacune des méthodes exécutant
une requête SQL. L’avantage de déclarer de telles méthodes ici, par rapport à la création de requête SQL dans une
classe normale, est que vous n’avez plus à vous préoccuper de problème de sqlinjection, de l’écriture fastidieuse des
requêtes SQL, etc...
Jelix 1.0.6
Guide du développeur
87 / 225

13.3.1 Balise <method>

Les méthodes sont déclarées via la balise <method>. Celle-ci doit avoir au moins un attribut, name, indiquant le
nom de la méthode. Il y a différent type de méthode. On indique le type via l’attribut type.
Une balise <method> peut contenir une ou plusieurs balises <parameter>, qui définissent des paramètres. Une
balise <parameter> doit avoir un attribut name indiquant son nom.
<parameter name="foo" />
...

Il est possible d’indiquer une valeur par défaut :


<parameter name="foo" default="20"/>

Voici les différents types de méthodes. La balise <conditions> est décrite plus loin.

13.3.2 Méthode de type select, selectfirst

Déclaration

<method type="select"> <!-- ou type="selectfirst" -->


<parameter />
<conditions />
<order />
<limit />
</method>

Une méthode de type select renvoient une liste d’objets "record", qui ont donc comme propriétés celles indiquées
dans la section record. Une méthode de type selectfirst renvoi le premier objet correspondant aux critères.
À noter qu’il n’est pas possible de limiter un select/selectfirst à un nombre réduit de propriétés. En effet, cela n’aurait
pas vraiment de sens au niveau du concept de "mapping" et serait même dangereux pour les données puisqu’alors
les propriétés non sélectionnées seraient vides dans le record, et si on fait ensuite un update derrière... Si on veut
sélectionner un nombre restreint des propriétés définies, la seule possibilité pour le moment est de créer un autre
DAO.
On peut ajouter un attribut distinct pour récupérer seulement les éléments distincts.
<method type="select" name="findThem" distinct="true">
..

La balise <conditions> (facultative) décrit une condition (la clause WHERE en SQL). Voir la section correspondante
plus loin.
On peut aussi ajouter une balise <order> qui permet de spécifier l’ordre des enregistrements récupérés (clause
ORDER en SQL). Il faut indiquer une ou plusieurs balises <orderitem>, qui contiennent un attribut property indiquant
le nom de la propriété sur lequel l’ordre s’effectue et un attribut way. L’attribut way doit contenir "asc" ou "desc" ou
un nom de paramètre de méthode (précédé alors par un $).
<order>
<orderitem property="foo" way="asc" />
</order>

À noter que property peut contenir, soit un nom d’une propriété, soit un nom de paramètre de la méthode (précédé
d’un $) qui doit alors contenir un nom de propriété.
Enfin, une balise <limit> optionnelle permet de restreindre le nombre d’enregistrement retournés.
Jelix 1.0.6
Guide du développeur
88 / 225

<limit offset="5" count="10" />

Les attributs count et offset contiennent soit un nombre, soit un nom de paramètre de méthode (précédé alors par un
$).
<method type="select" name="getFewRecord" >
<parameter name="count"/>
<parameter name="offset"/>
<limit offset="$offset" count="$count"/>
</method>

Utilisation

L’utilisation des méthodes déclarées en XML a été pensée pour être transparente vis-à-vis du développeur qui n’a
pas envie de se soucier de la déclaration du DAO.
Reprenons notre méthode getFewRecord. On veut normalement récupérer un tableau en PHP afin de manipuler plus
facilement les enregistrements. Rien de plus simple :
$dao = jDao::get(’module~list’); // Récupèration du DAO si ce n’est pas fait
$records = $dao->getFewRecord(10, 5); // Appel de la méthode XML avec ses ←-
arguments et récupération des données

foreach ($records as $record) // Parcours des données


jLog::log($record->name); // Accès au champ "name" d’un enregistrement

Ainsi, pour chaque méthode XML ajoutée dans le DAO, une méthode est générée et utilisable directement via PHP.
Comme pour toute requête SQL, il ne faut pas oublier de "fetcher" les données.

13.3.3 Méthode de type count

<method type="count">
<parameter />
<conditions />
</method>

ce type de méthode est équivalent à un SELECT COUNT(*), avec les conditions indiquées. Si on indique une
propriété sur laquelle il faut faire un distinct, via l’attribut distinct comme pour type="select", alors il sera fait un
SELECT COUNT(DISTINCT le_champ_correspondant).
13.3.4 Méthode de type delete

<method type="delete">
<parameter />
<conditions />
</method>

Génère une méthode qui execute une requête DELETE.


13.3.5 Méthode de type update

<method type="update">
<parameter />
<conditions />
<values />
</method>
Jelix 1.0.6
Guide du développeur
89 / 225

Ce type de méthode exécute une requête de type UPDATE. En plus des paramètres et des conditions, il faut indiquer
les valeurs que l’on met sur telle ou telle propriété avec les balises <value>.
<values>
<value property="foo" value="" expr=""/>
</values>

L’attribut property indique la propriété que l’on va mettre à jour. Comme dans les conditions, l’attribut value doit
contenir une valeur. Mais si on veut indiquer une expression SQL ou un paramètre de la méthode, il faut utiliser
l’attribut expr.
13.3.6 Clause conditions

Voici la description de la balise <conditions> qui peut être utilisée dans la plupart des méthodes précédentes.
<conditions logic="AND">
<eq property="foo" value="" expr=""/>
<neq property="foo" value="" expr=""/>
<lt property="foo" value="" expr=""/>
<gt property="foo" value="" expr=""/>
<lteq property="foo" value="" expr=""/>
<gteq property="foo" value="" expr=""/>
<like property="foo" value="" expr=""/>
<isnull property="foo"/>
<isnotnull property="foo"/>
<in property="foo" value="" expr=""/>
<notin property="foo" value="" expr=""/>
</conditions>

On peut mettre plusieurs balises <conditions> imbriquées pour faire des groupes or/and. Si l’attribut logic n’est pas
spécifié, il vaut AND par défaut. Sinon il doit valoir "OR" ou "AND".
L’attribut value doit contenir une valeur. Le type de cette valeur est celui de la propriété. Si on préfère utiliser une
expression SQL ou indiquer un paramètre de méthode, il faut utiliser l’attribut expr.

Cas de in/notin

<in> et <notin> sont les équivalents de foo IN (a, b, c) et foo NOT IN (a, b, c). L’usage de
value et expr est différente. Si vous avez une liste de valeurs statiques, vous les mettrez dans l’attribut value
comme vous le feriez en SQL :
<in property="foo" value="5,3,2" />

ou
<in property="foo" value="’toto’,’titi’,’tata’" />

Vous utiliserez expr quand vous aurez un paramètre de méthode (donc une liste de valeurs dynamiques) :
<in property="foo" expr="$liste" />

Ce paramètre doit obligatoirement contenir un tableau PHP de valeurs. Et l’attribut expr ne peut contenir autre
chose qu’un nom de paramètre.
Jelix 1.0.6
Guide du développeur
90 / 225

13.4 Développer des méthodes en php

Les méthodes déclarées en XML permettent de créer facilement des méthodes, et peuvent répondre à beaucoup de
situations. Néanmoins elles sont tout de même limitées dans la cadre de requêtes complexes. On ne peut pas créer des
requêtes complexes.
Une première solution serait de se créer une classe PHP classique, et utiliser jDb pour effectuer les requêtes. Cepen-
dant, lorsque les enregistrements sur lesquels on opère correspondent à ce qui a déjà été défini dans un DAO, il est
plus logique de pouvoir intégrer une telle méthode dans la factory d’un DAO.

13.4.1 Déclaration d’une méthode en PHP

C’est relativement simple à faire : il suffit de déclarer en XML une méthode de type "php" :
<method type="php" name="foo">
<parameter name="bar" />
<body><![CDATA[
ici le code php de la méthode
]]></body>
</method>

Les autres balises autorisées dans les autres types de méthodes (conditions, order...) ne peuvent être utilisées
ici, puisque vous êtes censés écrire vous même la requête SQL !
Vous devez indiquer bien sûr un nom à la méthode, et vous pouvez déclarer des paramètres comme d’habitude.

13.4.2 API interne d’une factory

Au niveau du code PHP, vous pouvez faire presque ce que vous voulez. Cependant :
– pour respecter le pattern DAO, et si vous renvoyez des résultats d’enregistrement, vous devez renvoyer des objets
qui sont des records du même type que ceux définis dans la DAO. Le nom de la classe du record correspondant se
trouve dans la propriété _DaoRecordClassName
– Pour effectuer les requêtes, vous devez utiliser l’objet jDbConnection placé dans la propriété _conn.
– Vous avez à votre disposition d’autres propriétés et méthodes qui vous facilitent le travail d’écriture.

Manière de coder

Vous avez deux manières de réaliser les méthodes PHP :


1. soit vous écrivez des requêtes quasiment "en dur", statiques
2. soit vous créez les requêtes à partir des informations (comme les noms de tables, les noms des champs, les types
de champs etc...) stockées dans la factory et le record.
La première façon permet d’avoir un fonctionnement un peu plus performant, et peut être plus simple à écrire. Mais
la deuxième évite d’avoir systématiquement à mettre à jour votre méthode quand vous modifiez certaines informations
dans la section datasources ou properties. Cependant notez qu’une fois en production, c’est la performance
qui prime. À vous de choisir.
Avec la deuxième façon de réaliser les méthodes PHP, vous aurez besoin de lire les informations sur les tables et les
propriétés. Sachez que vous trouverez ces informations dans plusieurs propriétés :
– $this->_primaryTable : l’alias de la table primaire,
– $this->_tables : une liste d’informations (voir la documentation de référence pour la description détaillée),
Jelix 1.0.6
Guide du développeur
91 / 225

– $this->getProperties() pour avoir des informations détaillées sur chaque propriétés d’un record (voir la
documentation de référence),
– $this->getPrimaryKeyNames() pour avoir la liste des noms des propriétés servant de clés primaires.
Et sur un record que vous aurez préalablement instancié, vous aurez aussi les même méthodes getProperties()
et getPrimaryKeyNames().
Notes :
– Pour les versions 1.0 beta 2.1 et inférieures, getPrimaryKeyNames() n’existait pas du tout (mais il y avait la
propriété $_pkFields équivalente sur la factory),
– Pour les versions 1.0 beta 2.1 et inférieures, getProperties() n’existait que sur les records.

Préparer les valeurs

Toutes les valeurs qu’on vous passe en paramètre, vous devez les "filtrer", les préparer, avant de les intégrer dans une
requête SQL, ceci pour éviter des problèmes de sécurité type SQL injection.
Pour cela, vous avez une méthode, _prepareValue(), qui accepte en paramètre une valeur, et un nom de type
de donnée (celle que l’on indique à l’attribut datatype de la balise property).
<method type="php" name="updateLabel">
<parameter name="id" />
<parameter name="label" />
<body><![CDATA[
$sql = ’update products set label=’ . $this->_prepareValue($label,’string’ ←-
);
$sql.= ’ where product_id=’.$this->_prepareValue($id,’integer’);
$this->_conn->exec($sql);
]]></body>
</method>

Ou encore
<method type="php" name="updateLabel">
<parameter name="id" />
<parameter name="label" />
<body><![CDATA[
$sql = ’update ’.$this->_tables[$this->_primaryTable][’realname’];
$sql.= ’ set label=’ . $this->_prepareValue($label,’string’);
$sql.= ’ where product_id=’.$this->_prepareValue($id,’integer’);
$this->_conn->exec($sql);
]]></body>
</method>

Faire des SELECTs

Normalement, quand vous faites des SELECT pour renvoyer un ensemble de résultats, vous devez retourner tous
les champs déclarés dans les balises property, donc faire aussi les jointures explicitement décrites. Et il faut aussi
retourner les résultats sous la forme des objets correspondants aux records. Pour éviter d’avoir à réécrire entièrement
les requêtes, il y a une série de propriétés indispensables :
– _selectClause : comporte la clause SELECT avec l’ensemble des champs déclarés
– _fromClause : comporte la clause FROM avec la déclaration des tables et des jointures externes
– _whereClause : comporte la clause WHERE avec les jointures internes
Une méthode qui renverrait un ensemble de résultats pourrait ressembler à ceci (ce type de requête pourrait être très
bien réalisé via les méthodes en XML, mais la complexité de la requête n’est pas l’objectif ici) :
Jelix 1.0.6
Guide du développeur
92 / 225

<method type="php" name="findByPrice">


<parameter name="price" />
<body><![CDATA[
$sql = $this->_selectClause.$this->_fromClause.$this->_whereClause;
$sql .= ($this->_whereClause == ’’?’ WHERE ’:’ AND ’);
$sql .= ’ price = ’. $this->_prepareValue($price,’float’);
$sql .= ’ ORDER BY label ASC’;

$rs = $this->_conn->query($sql);
$rs->setFetchMode(8,$this->_DaoRecordClassName);
return $rs;
]]></body>
</method>

– _whereClause peut être vide ou pas, c’est pourquoi il faut toujours tester,
– On a préparé la valeur avec _prepareValue(), ainsi on "protège" la requête,
– On a utilisé $this->_conn pour faire la requête, et on récupère donc un jDbRecordSet,
– Indispensable : on fait un setFetchMode(), pour indiquer le nom de la classe des objets qui contiendront les
enregistrements ! On y indique donc la classe des record du DAO,
– Enfin on retourne directement le recordSet : puisque jDbRecordSet implémente Iterator, on peut l’utiliser directe-
ment dans une boucle foreach, et on n’a donc pas besoin de créer une liste intermédiaire.

Récupération d’un seul enregistrement

C’est un peu le même principe que pour récupérer un ensemble :


<method type="php" name="findByLabel">
<parameter name="label" />
<body><![CDATA[
$sql = $this->_selectClause.$this->_fromClause.$this->_whereClause;
$sql .= ($this->_whereClause == ’’?’ WHERE ’:’ AND ’);
$sql .= ’ price = ’. $this->_prepareValue($label,’string’);

$rs = $this->_conn->query($sql);
$rs->setFetchMode(8,$this->_DaoRecordClassName);

$record = $rs->fetch();
return $record;
]]></body>
</method>

Notez le fetch().

13.4.3 Faire d’autres requêtes

Pour faire des UPDATE, DELETE, INSERT, rien de spécial à dire. Vous ne pouvez bien entendu pas utiliser _sel-
ectClause, _fromClause et _whereClause.
Vous avez par contre une méthode qui peut être utile pour les UPDATE et DELETE : _getPkWhereClauseFo-
rNonSelect(). Elle génère une condition pour la clause WHERE sur les clés primaires.
<method type="php" name="updateLabel">
<parameter name="id" />
<parameter name="label" />
<body><![CDATA[
Jelix 1.0.6
Guide du développeur
93 / 225

$sql = ’update products set label=’ . $this->_prepareValue($label,’string’ ←-


);
$keys = array_combine($this->getPrimaryKeyNames(), array($id));
$sql.= $this->_getPkWhereClauseForNonSelect($keys);

$this->_conn->exec($sql);
]]></body>
</method>

Même si l’intérêt est limité quand il y a une seule clé primaire, il augmente quand il y en a plusieurs.
Note :
– Pour les versions de Jelix 1.0 beta 2.1 et inférieures, vous deviez utiliser $this->_pkFields au lieu de $th-
is->getPrimaryKeyNames().

13.5 Évènements automatiques

Une factory de DAO peut générer automatiquement des évènements pour certains types de méthodes.

13.5.1 Évènements des méthodes natives

Les méthodes update, insert, delete et deleteby peuvent générer des évènements, soit avant la fonction, soit après la
fonction, soit avant et après. Pour les activer, il faut indiquer les évènements voulus dans l’attribut events de la balise
factory. Ils doivent être séparés par une virgule. Les noms possibles sont : deletebefore, deleteafter, updatebefore,
updateafter, insertbefore, insertafter, deletebybefore, deletebyafter.
Voici les noms des évènements générés avec les noms de leurs paramètres, sachant qu’ils ont tous un paramètre dao
qui contient le sélecteur du dao.
– daoDeleteBefore : key (valeurs des clés du record à supprimer)
– daoDeleteAfter : key, result (1 si l’enregistrement est supprimé)
– daoDeleteByBefore : key, criterias (objet jDaoConditions)
– daoDeleteByAfter : key, criterias, result (nombre d’enregistrements supprimés)
– daoUpdateBefore : record (objet record à mettre à jour)
– daoUpdateAfter : record
– daoInsertBefore : record
– daoInsertAfter : record
Exemple :
<factory events="deleteAfter, insertAfter"> ...

Et un listener possible :
class myListener extends jEventListener{

function onDaoDeleteAfter ($event) {


$dao = ;
if ($event->getParam(’dao’) == ’mymodule~thedao’) {
$key = $event->getParam(’key’);
//...
}
}
Jelix 1.0.6
Guide du développeur
94 / 225

13.5.2 Évènements des methodes personnalisées

Pour les méthodes personnalisées (celles que vous décrivez en XML), et uniquement les méthodes de type update ou
delete, vous pouvez indiquer l’attribut eventbefore, et/ou eventafter qui doivent contenir true ou false.
Les évènements générés sont alors daoSpecificUpdateBefore, daoSpecificUpdateAfter, daoSpecificDeleteBefore et
daoSpecificDeleteAfter. Ils ont pour paramètre
– dao, contenant le selecteur du dao conçerné
– method, le nom de la méthode
– params, contenant la liste des paramètres.
Jelix 1.0.6
Guide du développeur
95 / 225

Chapitre 14

Formulaires classiques

Créer et gérer des formulaires "à la main" (par opposition aux automatismes offert par le système de formulaire
jForms), n’est pas trés différent par rapport à ce que l’on fait dans une application PHP classique. Quelques petites
choses sont cependant à savoir pour profiter au mieux de ce qu’offre Jelix dans ce cas.

14.1 Les actions à mettre en oeuvre

L’implémentation très simpliste d’un formulaire consistera au développement de deux actions (les noms sont pure-
ment fictifs et servent juste d’exemple) :
– une action "show" d’affichage de formulaire
– une action "save" qui traite les données du formulaire (après le submit) et affiche le résultat
Mais dans la plupart des cas, pour répondre correctement aux erreurs, pour éviter que l’utilisation des boutons
"refresh" des navigateurs provoque une nouvelle exécution du traitement des données (action "save"), etc..., il vaut
mieux avoir ce genre de liste d’actions :
– une action "prepare" qui prépare les données pour un nouveau formulaire (initialisation en session par exemple,
avec lecture des données initiales en base de données par exemple) et redirige vers "show"
– une action "show" qui affiche le formulaire avec les données en sessions, et affiche les éventuelles erreurs de saisie.
– une action "save" qui vérifie les données saisies. Si il y a des erreurs, les sauve en session et redirige vers "show",
ou alors sauve les données et redirige vers "end"
– une action "end", qui nettoie les données en session, et affiche une page de confirmation, ou redirige vers une autre
action quelconque...

14.2 Création d’un formulaire

Vous utiliserez en général un template, dans lequel vous y mettrez vos balises html de formulaires. Par exemple :
<form action="index.php" method="POST">
<fieldset> <legend>Indiquez votre identité</legend>
<input type="hidden" name="module" value="monmodule" />
<input type="hidden" name="action" value="default_save" />
<table>
<tr>
<td><label for="champs-nom">Votre nom</label></td>
<td><input type="text" name="nom" id="champs-nom" /></td>
</tr>
<tr>
Jelix 1.0.6
Guide du développeur
96 / 225

<td><label for="champs-prenom">Votre prénom</label></td>


<td><input type="text" name="prenom" id="champs-prenom" /></td>
</tr>
</table>
</fieldset>
<p><input type="submit" value="Valider" />
</form>

Vous pouvez bien sûr y ajouter du javascript pour vérifier les données saisies coté client et utiliser tous les types de
champs de saisies HTML.
Par contre, l’exemple n’est pas totalement bon, dans la mesure où l’url est en dur dans le formulaire. Cela est
problématique par exemple quand on utilise des urls significatives, qu’on les change, ou qu’on veuille réutiliser dans
un autre projet. En effet, suivant l’url choisie, le contenu de l’attribut action peut être différent, le nombre de champs
cachés aussi.
Il est donc préférable d’utiliser les plugins de templates formurl et formurlparam, auxquels vous indiquez le sélec-
teur de l’action de traitement du formulaire, et de la liste des paramètres (comme quand vous appelez jUrl : :get()). Le
premier sert à générer l’url à mettre dans l’attribut action, et l’autre à générer les champs cachés contenant les éven-
tuels paramètres supplémentaires propres à l’action. Vous devez toujours utiliser les deux ensembles. Le formulaire
devient alors :
<form action="{formurl ’monmodule~default:save’}" method="POST">
<fieldset> <legend>Indiquez votre identité</legend>
{formurlparam ’monmodule~default:save’}
<table>
...
</table>
</fieldset>
<p><input type="submit" value="Valider" />
</form>

Le formulaire résultant sera le même que le premier exemple si le moteur d’url est celui par défaut, mais pourrait
devenir le formulaire suivant si le moteur d’url significant est activé et que l’url correpondante à l’action indiquée est
/user/save (sans paramètres supplémentaires, d’où l’absence ici de champs cachés) :
<form action="/user/save" method="POST">
<fieldset> <legend>Indiquez votre identité</legend>
<table>
...
</table>
</fieldset>
<p><input type="submit" value="Valider" />
</form>

14.3 Traitement des données en retour

Dans l’action servant à traiter les données, vous récupèrerez celles-ci grâce à $this->param(’champs’) dans votre
contrôleur. Vous avez d’autres méthodes similaires, comme $this->intParam(’champs’), $this->floatParam(’champs’)
et $this->boolParam(’champs’), qui permettent de récupérer directement les valeurs sous un type particulier (voir la
page sur les contrôleurs).
Vous pouvez utiliser en plus jFilter, qui est une classe permettant de vérifier le format des données (utilise l’extension
filter quand Jelix est généré pour PHP 5.2). exemple :
Jelix 1.0.6
Guide du développeur
97 / 225

function save() {
$email = $this->param(’email’);
if ($email === null) {
//.. ici erreur, l’email est obligatoire
}
if( ! jFilter::isEmail($email)){
// erreur, email mal saisie
}
//....
}

Voir la documentation de référence de jFilter


Jelix 1.0.6
Guide du développeur
98 / 225

Chapitre 15

jForms : des formulaires automatiques

jForms est un système complet qui facilite le travail du développeur pour créer des formulaires. Vous décrivez votre
formulaire dans un fichier xml, et par le biais d’une API relativement simple et de plugins de template, jForms
s’occupe automatiquement :
– de générer le formulaire HTML, en affichant des indications sur les champs qui sont en erreur, des indications sur
les champs obligatoires, l’aide sur chaque champ, sachant que l’affichage est hautement personnalisable.
– de générer les labels en tenant compte de l’accessibilité
– de générer le code javascript qui validera les données coté client
– de valider les données saisies côté serveur
– d’afficher les erreurs au niveau du formulaire, soit après validation en javascript, avant l’envoi du formulaire, soit
lors de l’affichage du formulaire (après la validation côté serveur)
– de gérer plusieurs instances d’un même formulaire en même temps (permettant d’éditer plusieurs enregistrements
en même temps)
– d’initialiser un formulaire à partir de données d’un ou plusieurs DAO (que ce soit au niveau des valeurs des
champs, ou du remplissage de listbox, liste de boutons radio etc)
– de sauver les données saisies dans des DAOs
– de sauvegarder les fichiers uploadés
Dans Jelix 1.1, jForms pourra aussi :
– générer d’autres types de formulaires (en ajax, XUL, XForms etc...) sans changer une seule ligne de code, par le
biais de plugins.
– de prendre en charge automatiquement des champs de type captchas
– d’afficher des champs d’édition WYSIWYG
– et bien d’autres choses ;-)
jForms est composé de trois parties distinctes :
– Des fichiers xml qui permettent de décrire vos formulaires.
– l’API côté serveur qui permet de créer une instance d’un formulaire et de gérer les données qu’il contient
– des plugins de templates pour afficher une instance d’un formulaire.
À partir d’un fichier jforms XML, jForms gère un objet (héritant de jFormsBase) créé à partir des informations
contenues dans le fichier XML, et permettant d’initialiser le contenu du formulaire, de gérer son contenu, de le
sauvegarder etc. Par conséquent il contient toutes les valeurs saisies, stockées dans des variables de cet objet (variables
de formulaire).
C’est aussi à partir d’un objet jforms que des plugins de templates permettent d’afficher les éléments HTML corres-
pondant.
Jelix 1.0.6
Guide du développeur
99 / 225

15.1 Format des fichiers jForms

jForms se base sur des fichiers descriptifs en XML. Tout formulaire est décrit en XML, avec une grammaire assez
simple, à mi-chemin entre HTML et XForms.
Ces fichiers XML sont à placer dans un répertoire forms des modules et doivent avoir comme nom foo.form.xml,
où foo est le nom identifiant du formulaire (que vous choisissez bien sûr). Cet identifiant est utilisé ensuite dans les
sélecteurs.
Par exemple "monModule~produit" fait référence au formulaire monModule/forms/produit.form.xml.
– Format version 1.0

15.1.1 Format version 1.0

La version 1.0 du format décrit dans cette page est utilisable depuis Jelix 1.0. Dans les betas de Jelix 1.0, il est
possible que certains des attributs ou balises n’étaient pas disponibles, mais ces différences ne sont plus documentées.

Structure principale

Le document XML que vous écrivez dans un fichier jForms est composé d’une balise <form> comme racine.
<?xml version="1.0" encoding="utf-8"?>
<form xmlns="http://jelix.org/ns/forms/1.0">

</form>

Dans cette balise, vous indiquerez les balises correspondantes à chacun des contrôles (champs de saisies) composant
le formulaire. Le traitement et l’affichage de ces contrôles se feront dans le même ordre que celui de leur apparition
dans le document.
– *Notez que le namespace pour cette version du format est http ://jelix.org/ns/forms/1.0**

Propriétés communes aux contrôles

Identifiant

Chaque contrôle doit avoir un identifiant (= un nom). Vous devez en indiquer un avec l’attribut ref. Cet identifiant
correspond en fait à ce qu’on appelle une variable de formulaire et qui contiendra la valeur saisie.
Exemple :
<input ref="nom">
</input>

Note : quand vous voulez utiliser un formulaire avec un ou plusieurs DAO, il est judicieux d’utiliser les mêmes noms
que les propriétés des DAO, afin de pouvoir utiliser les mécanismes de chargement et sauvegarde automatique de
jForms avec les DAO.

Libellé

Tout champ de saisie doit contenir un libellé indiqué au moyen de la balise <label> :
<input ref="nom">
<label>Votre nom</label>
</input>
Jelix 1.0.6
Guide du développeur
100 / 225

On peut indiquer une locale plutôt qu’une chaîne "en dur" :


<input ref="nom">
<label locale="mymodule~forms.input.name"/>
</input>

Messages informatifs

Un message d’aide (optionnel) peut être affiché en même temps que le contrôle de saisie, grâce à la balise <help> :
vous y inscrivez soit le message d’aide, soit la locale (via l’attribut locale).
<input ref="datenaissance" type="date">
<label locale="mymodule~forms.input.naissance"/>
<help>Indiquez votre date de naissance, en respectant le format aaaa-mm-jj</ ←-
help>
</input>

ou

<input ref="datenaissance" type="date">


<label locale="mymodule~forms.input.naissance"/>
<help locale="mymodule~forms.input.naissance.help"/>
</input>

Dans les formulaires en HTML, un point d’interrogation s’affichera à côté du champ de saisie et le message d’aide
s’affichera lors d’un clique sur ce point d’interrogation.
Un autre type de message informatif peut être affiché sous forme de tooltip. Il faut pour cela utiliser la balise <hint>,
qui s’utilise comme la balise <help>.

Messages d’erreurs

Quand le contenu du champs de saisie est invalide, ou que la saisie est manquante alors qu’elle est requise, jForms
affiche des messages d’erreurs prédéfinis. Cependant vous pouvez fournir vous même ces messages au moyen de la
balise <alert>. Un attribut type permet de définir soit le message pour l’erreur d’invalidité, soit le message pour la
saisie obligatoire. Et comme les balises précédentes, vous pouvez indiquer le message complet, ou indiquer une locale
au moyen de l’attribut locale.
<input ref="datenaissance" type="date">
<label locale="mymodule~forms.input.naissance"/>
<alert type="required" locale="mymodule~forms.input.naissance.error.required" ←-
/>
<alert type="invalid">Le format de la date à respecter pour la saisie est aaaa ←-
-mm-jj</alert>
</input>

Saisie obligatoire

Pour rendre la saisie obligatoire sur un champ de saisie, il faut mettre l’attribut required avec la valeur true. Cet
attribut n’est pas valable sur l’élement <submit>, <checkbox> et <output>.

Lecture seule

Il est possible d’empêcher la modification d’un champ de saisie (c’est toutefois rare d’avoir à le faire). Pour cela, il
faut mettre l’attribut readonly avec la valeur true. Cet attribut n’est pas valable sur l’élément <submit> et <output>.
Jelix 1.0.6
Guide du développeur
101 / 225

Champs de saisie

Saisie de texte simple

Pour afficher un simple champs de saisie, il faut utiliser la balise <input>. Vous devez y mettre l’attribut ref, et vous
pouvez utiliser les balises <label>, <hint>, <alert>, <help> ainsi que les attributs readonly et required. Vous pouvez
indiquer aussi cinq attributs supplémentaires : type, defaultvalue, size, minlength et maxlength.
– *defaultvalue** permet d’indiquer une valeur par défaut qui sera affichée quand le formulaire est vide. Vous
pouvez mettre la valeur "now" pour les champs de saisies de dates. La valeur par défaut sera alors la date de
maintenant.
– *size** permet d’indiquer la largeur de la boite de saisie en nombre de caractères.
– *maxlength et minlength** permet d’ajouter une contrainte sur la valeur saisie : la longueur minimale et maximale
de la chaine de caractère saisie. Ces deux attributs ne sont utilisables que pour le type="string".
– *type** permet d’indiquer le format de donnée que l’utilisateur doit respecter. Au moment de l’envoi du formu-
laire, il y aura une vérification en javascript du contenu saisie, mais aussi une vérification coté serveur (au cas où
le javascript est désactivé notamment) lors de l’appel à la méthode check() sur l’objet formulaire.
Voici les valeurs possibles pour l’attribut type et ce que doit taper l’utilisateur :
– "string" : chaîne contenant n’importe quel caractère. (c’est le type par défaut)
– "boolean" : la valeur du champs doit être obligatoirement "true" ou "false"
– "decimal" : un nombre avec ou sans virgule
– "integer" : un nombre entier
– "hexadecimal" : un nombre hexadecimal (chiffres de 0 à 9 et lettres de a à f)
– "datetime", "date", "time" : une date et heure, une date ou une heure. Le format précis est respectivement "aaaa-
mm-jj hh :mm :ss", "aaaa-mm-jj", "hh :mm :ss".
– "localedatetime", "localedate", "localetime" : une date et heure, une date ou une heure, mais dans le format de la
langue de l’utilisateur. Par exemple, pour un site en français, le format de la date devra être "jj/mm/aaaa", et pour
un site en anglais "mm/jj/aaaa".
– "url" : la chaîne doit être une URL valide
– "email" : un email
– "ipv4" : une adresse IP v4
– "ipv6" : une adresse IP v6
Un exemple de champs de saisie simple :
<input ref="email" type="email">
<label locale="monmodule~monform.email.label" />
<hint>L’email doit être valide</hint>
</input>

Saisie de texte multiligne

Pour permettre la saisie d’un texte de plusieurs lignes, il faut utiliser la balise <textarea>. Vous devez y mettre
l’attribut ref, et vous pouvez utiliser les balises <label>, <hint>, <alert>, <help> ainsi que les attributs readonly et
required. Il y a plusieurs attributs spécifiques à cette balise : defaultvalue, rows, cols, minlength et maxlength.
– *defaultvalue permet d’indiquer une valeur à afficher automatiquement pour un nouveau formulaire, tandis
que rows et cols** permettent de fixer la taille du champs de saisie en hauteur et largeur (comme le textarea en
HTML).
Un exemple :
<textarea ref="message">
<label locale="monmodule~monform.message.label" />
<hint>Saisissez ici le message</hint>
</textarea>
Jelix 1.0.6
Guide du développeur
102 / 225

– *maxlength et minlength** permettent d’ajouter une contrainte sur la valeur saisie : la longueur minimale et
maximale de la chaine de caractères saisie.

Mot de passe

Pour la saisie d’un mot de passe ou tout autre renseignement qui doit être caché lors de la saisie, vous utiliserez
la balise <secret>. Vous devez y mettre l’attribut ref, et vous pouvez utiliser les balises <label>, <hint>, <alert>,
<help> ainsi que les attributs readonly et required.
<secret ref="password">
<label>Votre mot de passe</label>
<hint>Indiquez le mot de passe que l’on vous a donné à l’inscription</hint>
</secret>

Vous pouvez utiliser l’attribut size pour indiquer la largeur du champs de saisie.
Il est souvent utile de demander à l’utilisateur de saisir une deuxième fois un nouveau mot de passe, lors d’une
inscription par exemple. jForms gère cela automatiquement. Il suffit d’indiquer la balise <confirm> dans la balise
<secret>, et le formulaire HTML généré contiendra deux champs de saisie. La balise <confirm> doit contenir soit
l’intitulé du libellé pour la confirmation, soit un attribut locale contenant le selecteur de la locale pour le libellé de la
confirmation.
<secret ref="newpassword">
<label>Mot de passe</label>
<hint>Indiquez un nouveau mot de passe</hint>
<confirm>Retapez ce mot de passe</confirm>
</secret>

Cela génèrera en gros, pour un formulaire html :


<label for="newpassword">Mot de passe</label>
<input type="password" id="newpassword" name="newpassword" title="Indiquez ←-
un nouveau mot de passe"/>

<label for="newpassword_confirm">Retapez ce mot de passe</label>


<input type="password" id="newpassword_confirm" name="newpassword_confirm" ←-
/>

Case à cocher seule

Pour afficher une case à cocher, utiliser la balise <checkbox>. Vous devez y mettre l’attribut ref, et vous pouvez
utiliser les balises <label>, <hint>, <alert>, <help> ainsi que l’attribut readonly (mais pas required).
<checkbox ref="souvenir">
<label>Se souvenir de moi</label>
<help>Cochez cette case si vous voulez être identifié automatiquement la ←-
prochaine fois</help>
</checkbox>

Par défaut, la valeur de la case à cocher, que vous récupèrerez une fois le contenu du formulaire reçu, vaudra 0 si la
case n’a pas été cochée, ou 1 si elle l’a été.
Vous pouvez décider d’autres valeurs pour chacun de ces deux états. Il suffit d’indiquer les attributs valueoncheck
et valueonuncheck (qui valent donc par défaut, respectivement 1 et 0). Exemple :
Jelix 1.0.6
Guide du développeur
103 / 225

<checkbox ref="souvenir" valueoncheck="O" valueonuncheck="N">


<label>Se souvenir de moi</label>
<help>Cochez cette case si vous voulez être identifier automatiquement la ←-
prochaine fois</help>
</checkbox>

Notez que lorsque vous afficherez un formulaire prérempli, la case sera cochée ou non en fonction de la valeur
initiale, selon que celle-ci corresponde à la valeur de valueoncheck ou de valueonuncheck.

Liste de cases à cocher

On peut avoir à afficher une série de case à cocher qui correspondent à des choix multiples, par exemple afficher
une liste de choses à acheter, et l’utilisateur coche les articles qu’il veut acheter. Pour cela on utilisera la balise
<checkboxes> (avec un S à la fin).
Vous devez y mettre l’attribut ref, et vous pouvez utiliser les balises <label>, <hint>, <alert>, <help> ainsi que les
attributs readonly et required.
Il vous faut aussi indiquer la liste des valeurs possibles et leurs libellés. Voir la section "sources de données" plus
bas.
Exemple :
<checkboxes ref="articles">
<label>Sélectionnez les articles que vous voulez acheter :</label>
<item value="54">sucre</item>
<item value="27">steack</item>
<item value="32">jus d’orange</item>
</checkboxes>

Ceci affichera une série de trois cases à cocher, ayant pour intitulé "sucre", "steack" et "jus d’orange". Quand le
formulaire sera envoyé au serveur, la valeur que vous recevrez pour la variable de formulaire "articles", sera un
tableau PHP contenant les valeurs des case qui ont été cochée. Par exemple, si l’utilisateur a coché "steack", coté
serveur vous recevrez array(27). Si il a en plus coché "sucre", vous recevrez array(54, 27).
(voir la page sur la gestion du contenu d’un formulaire coté serveur)

Boutons radios

Les boutons radios vont toujours par groupe, d’au moins 2. Pour déclarer un groupe de boutons radio, vous utiliserez
la balise <radiobuttons>.
Vous devez y mettre l’attribut ref, et vous pouvez utiliser les balises <label>, <hint>, <alert>, <help> ainsi que les
attributs readonly et required. Comme pour les autres contrôles de type liste, vous devez indiquer la liste des valeurs
possibles et leurs libellés. Voir la section "sources de données" plus bas.
Exemple :
<radiobuttons ref="couleur">
<label>Couleur de votre voiture:</label>
<item value="r">Rouge</item>
<item value="b">Bleue</item>
<item value="v">Verte</item>
<item value="j">Jaune</item>
</radiobuttons>

Ceci affichera une série de 4 boutons radio, et la valeur choisie sera stockée dans la variable de formulaire "couleur".
Jelix 1.0.6
Guide du développeur
104 / 225

Liste déroulante

La balise <menulist> affiche une liste déroulante (<select size="1"> en HTML), et de par sa nature, un seul choix
est possible. Vous devez y mettre l’attribut ref, et vous pouvez utiliser les balises <label>, <hint>, <alert>, <help>
ainsi que les attributs readonly et required. Comme pour les autres contrôles de type liste, vous devez indiquer la liste
des valeurs possibles et leurs libellés. Voir la section "sources de données" plus bas.
Exemple :
<menulist ref="ville">
<label>votre ville :</label>
<item value="75000">Paris</item>
<item value="37000">Tours</item>
<item value="44000">Nantes</item>
<item value="69000">Lyon</item>
</menulist>

La variable de formulaire contiendra la valeur de l’item sélectionné.

Liste non déroulante

Les listes déroulantes, ou encore listbox (Équivalent de la balise <select> en HTML), sont déclarées au moyen
de balise <listbox>. Vous devez y mettre l’attribut ref, et vous pouvez utiliser les balises <label>, <hint>, <alert>,
<help> ainsi que les attributs readonly et required. Comme pour les autres contrôles de type liste, vous devez indiquer
la liste des valeurs possibles et leurs libellés. Voir la section "sources de données" plus bas.
<listbox ref="rubrique">
<label>Rubrique préférée :</label>
<item value="1">Tutoriels</item>
<item value="2">Manuels</item>
<item value="3">Forums</item>
</listbox>

Vous pouvez indiquer un attribut size qui permet d’indiquer le nombre d’items affichables en même temps (donc la
hauteur de la liste). Par défaut, elle vaut 4.
Par défaut, un seul choix est possible. Cependant en ajoutant l’attribut multiple="true", l’utilisateur pourra sélec-
tionner plusieurs éléments de la liste (dans une page HTML, il faut que l’utilisateur appuie sur la touche CTRL en
même temps qu’il clique sur un item). Dans ce cas, dans la variable de formulaire "rubrique", au lieu d’avoir une
simple valeur correspondant à l’item sélectionné, vous aurez un tableau PHP avec toutes les valeurs des items choisis.

Upload de fichier

Pour permettre à l’utilisateur de télécharger un fichier vers le serveur, vous pouvez utiliser la balise <upload> (équi-
valent de <input type="file"> en HTML). Comme pour les autres contrôles, vous devez y mettre l’attribut ref, et vous
pouvez utiliser les balises <label>, <hint>, <alert>, <help> ainsi que les attributs readonly et required.
Deux attributs supplémentaires sont à votre disposition, pour contrôler la nature et la taille des fichiers, qui sont
respectivement mimetype (devant contenir un ou plusieurs type mime) et maxsize (taille en octets).
<upload ref="photo" mimetype="image/jpeg;image/png" maxsize="20000">
<label>Votre photo</label>
</upload>

À la réception du fichier, jForms vérifie si il correspond au type et à la taille indiqués, et l’on peut ensuite lui indiqué
où stocker le fichier téléchargé. La variable de formulaire contiendra le nom du fichier.
Jelix 1.0.6
Guide du développeur
105 / 225

Boutons de validation

Dans un formulaire, il faut bien sûr au moins un bouton qui permette à l’utilisateur de valider la saisie et envoyer les
données au serveur. Vous déclarez un bouton de ce type avec la balise <submit>. Comme pour les autres contrôles,
vous devez y mettre l’attribut ref, et vous pouvez utiliser les balises <label>, <hint>, <alert>, <help> (mais pas les
attributs readonly ni required).
<submit ref="submit">
<label>Ok</label>
</submit>

La variable de formulaire correspondante ne contiendra rien d’intéressant. À moins que vous ayez besoin de plusieurs
boutons de soumission, représentant par exemple l’action à effectuer après l’envoi du formulaire comme un bouton
"prévisualiser" et un autre "sauvegarder". Dans ce cas, vous utiliserez comme pour les autres contrôles de type liste,
un dao ou les balises item :
<submit ref="valider">
<label>Veuillez valider</label>
<item value="preview">Prévisualiser</item>
<item value="svg">Sauvegarder</item>
</submit>

Dans la variable de formulaire "valider", vous aurez alors la valeur "preview" ou "svg", et vous pourrez agir en
fonction de ces valeurs dans le contrôleur. Au niveau du formulaire HTML, cela affichera deux boutons avec leurs
libellés respectifs "Prévisualiser" et "Sauvegarder".

Bouton reset

Pour afficher un bouton reset avec jForms, il faut utiliser la balise <reset> :
<reset ref="reinit">
<label>Réinitialiser</label>
</reset>

Affichage de valeurs

La balise <output> ne sert qu’à afficher une valeur. Cette dernière ne sera donc pas éditable. Cela peut être utile
pour afficher un formulaire de tout un enregistrement sans pour autant éditer tout les champs. Vous devez y mettre
l’attribut ref, et vous pouvez utiliser les balises <label>, <hint>, <alert>, <help> (mais pas les attributs readonly ni
required).
<output ref="categorie">
<label>Catégorie</label>
</output>

Source de données

Les contrôles tels que menulist, listbox et radiobuttons, checkboxes contiennent plusieurs choix de valeurs pour
l’utilisateur. Il convient donc d’indiquer dans ces contrôles la manière dont jForms va récupérer les valeurs et libellés
de ces choix.
Il y a pour le moment trois façons de faire :
1. indiquer ces choix en dur dans le fichier jForms (données statiques)
2. indiquer un DAO qui permettra de les récupérer.
3. indiquer une classe qui fournis ces données.
Jelix 1.0.6
Guide du développeur
106 / 225

Données statiques

Elles doivent être indiquées au moyen d’une ou plusieurs balises <item>. La valeur du choix doit être mis dans un
attribut value. Le libellé du choix doit être mis en tant que contenu de la balise <item>, ou dans un fichier de locale et
alors vous indiquez la locale au moyen de l’attribut locale. Si aucun label est indiqué, le label sera la valeur. Exemple :
<checkboxes ref="objets">
<label>Vous avez </label>
<item value="maison">Une maison</item>
<item value="voiture" locale="mymodule~myform.item.car.label" />
<item value="bateau"/>
</checkboxes>

Données dynamiques avec un DAO

Le contenu d’une liste peut être rempli grâce à un DAO. Vous devez alors indiquer au moins 3 attributs :
1. dao, indiquant le sélecteur de la DAO à utiliser
2. daomethod, indiquant la méthode de la DAO qui génère la liste des choix
3. daolabelproperty, indiquant quelle est la propriété de la DAO qui contient le libellé du choix
La valeur de chaque choix sera la valeur de la clé primaire de la DAO. Cependant, si vous voulez indiquer une autre
propriété de la DAO, vous pouvez l’indiquer dans l’attribut daovalueproperty.
Exemple :
<menulist ref="conf" dao="testapp~config"
daomethod="findAll"
daolabelproperty="cvalue"
daovalueproperty="ckey">
<label>Sélectionnez l’élément de configuration à éditer</label>
</menulist>

Données dynamiques avec une classe

Si vous voulez fournir les données dynamiquement d’une autre manière que par un dao, vous pouvez créer une classe,
qui devra implémenter l’interface jIFormDatasource. Elle sera stockée dans un répertoire classes/ d’un module, et
vous l’indiquerez via l’attribut dsclass.
Exemple de classe :
class listDatas implements jIFormDatasource
{
protected $formId = 0;

protected $datas = array();

function __construct($id)
{
$this->formId = $id;
$this->datas = array(0 => ’test’,
1 => ’test 2’,
2 => ’Id = ’. $id);
}

public function getDatas()


Jelix 1.0.6
Guide du développeur
107 / 225

{
return ($this->datas);
}

public function getLabel($key)


{
if(isset($this->datas[$key]))
return $this->datas[$key];
else
return null;
}

Et dans le fichier jforms :


<menulist ref="icone" dsclass="monmodule~listDatas">
<label locale="elements.crud.label.icone" />
</menulist>

Autre source de données

Si l’utilisation d’un DAO, d’une classe ou de données statiques n’est pas suffisant pour vous, regardez la section
"Définir les choix d’un champs à multiple choix" dans la page Utilisation de jforms.
Dans ce cas là, vous ne devez pas indiquer de balises <item> ou d’attributs dao*/dsclass.

Présélection de valeurs

Dans une liste de choix, il est possible d’indiquer des valeurs par défaut qui seront sélectionnées. Vous avez trois
façons de le faire :
1. soit indiquer un attribut selected="true" sur chaque balise item voulue si vous utilisez celles-ci. Plusieurs items
peuvent avoir un attribut selected seulement sur les listes de case à cocher (checkboxes), soit sur une listbox
"multiple". Dans les autres cas, un seul item doit avoir l’attribut selected.
2. soit indiquer un attribut selectedvalue sur la balise du contrôle, en y stockant la valeur séléctionnée. Cependant
vous ne pouvez indiquer qu’une valeur, donc un seul choix ne sera sélectionné par défaut
3. soit indiquer un element <selectedvalues> contenant des éléments <value>. Cette manière de faire est toute
indiquée pour checkboxes et listbox en multiple, et quand la source de données est une dao.
Exemples :
<radiobuttons ref="home">
<label>Vous habitez</label>
<item value="pa" selected="true">Paris</item>
<item value="ma">Marseille</item>
<item value="ly">Lyon</item>
<item value="br">Brest</item>
<item value="li">Lille</item>
<item value="bo">Bordeaux</item>
</radiobuttons>

<menulist ref="conf" selectedvalue="foo.bar"


dao="testapp~config"
daomethod="findAll"
Jelix 1.0.6
Guide du développeur
108 / 225

daolabelproperty="cvalue"
daovalueproperty="ckey">
<label>Sélectionnez l’élément de configuration à éditer</label>
</menulist>

<listbox ref="objets" required="true" multiple="true">


<label>Vous avez </label>
<item value="maison">Une maison</item>
<item value="voiture">Une voiture</item>
<item value="bateau">Un bateau</item>
<item value="assiette">Une assiette</item>
<selectedvalues>
<value>maison</value>
<value>bateau</value>
</selectedvalues>
</listbox>

15.2 Utiliser un formulaire dans un contrôleur

Les données d’un formulaire jforms sont stockées en sessions. On manipule ces données au travers d’un objet formu-
laire, instance d’une classe héritant de jFormsBase. Cette classe est générée automatiquement à partir du fichier XML
que vous fournissez. Comme pour les DAOs, elle est stockée dans un cache évitant de la recréer à chaque utilisation.
Dans les contrôleurs, vous créez, récupérez et détruisez cet objet formulaire via les méthodes statiques de l’objet
jForms.

15.2.1 Les actions à mettre en oeuvre

Comme il est déjà expliqué dans le guide sur les formulaires classiques, pour faire une gestion complète de la saisie
d’un formulaire, la création des actions suivantes est recommandée (les noms utilisés sont juste à titre d’exemple,
vous utilisez les noms que vous voulez bien sûr) :
– une action "prepare" qui crée une nouvelle instance d’un objet formulaire avec jforms. S’il faut pré-remplir le
formulaire, cette action devra le faire aussi. Redirection vers "show".
– une action "show" qui récupère l’instance du formulaire, et l’utilise dans un template pour l’afficher avec les éven-
tuelles erreurs de saisie trouvées lors d’une validation précédente. La soumission du formulaire par l’utilisateur
dirigera vers l’action "save".
– une action "save". l’instance du formulaire est récupérée auprès de jForms, et elle est remplie avec les données
reçues du navigateur. Elle pourra ensuite lancer la vérification des données dans le formulaire. Si il y a des erreurs,
il y aura une redirection vers "show". Sinon on pourra traiter les données (sauvegarde en base de donnée par
exemple) et ensuite rediriger vers "end"
– une action "end", qui détruira l’instance du formulaire jforms (ce qui effacera les données correspondantes en ses-
sion), et affichera éventuellement une page de confirmation, ou alors redirigera vers une autre action quelconque...

15.2.2 Créer une instance d’un formulaire

Avant de pouvoir utiliser jForms, il faut bien sûr créer un fichier xml décrivant le formulaire, et il faut ensuite avant
toute utilisation, qu’une de vos actions crée une instance de votre formulaire. Cela se fait au moyen de la méthode
statique create de la classe jForms. Comme toutes les autres méthodes statiques de la class jForms, elle prend en
premier argument le sélecteur du fichier xml, et un deuxième argument facultatif qui est un identifiant de l’instance à
créer.
Jelix 1.0.6
Guide du développeur
109 / 225

En admettant que votre fichier xml soit "contact.form.xml" dans le module "main" :
$form = jForms::create("main~contact");

La variable $form contiendra un objet qui aura pour classe, celle créée lors de la lecture du fichier XML, et qui hérite
de jFormsBase. Vous utiliserez ensuite cette variable $form pour manipuler les données du formulaire.
Dans cette exemple, nous n’indiquons pas le deuxième paramètre. En effet celui-ci ne sert que lorsque l’on veut
éditer des informations qui existent déjà. Par exemple, pour un formulaire pour éditer un produit qui est en base de
donnée, on indiquera l’identifiant de ce produit.
Pourquoi ? Avec un navigateur web, l’utilisateur a la possibilité d’ouvrir plusieurs pages à la fois. Il a donc la possi-
bilité d’afficher plusieurs fois la même page qui afficherait par exemple ce formulaire d’édition de produit, mais avec
à chaque fois un produit différent. Pour éviter qu’à chaque fois que l’on ouvre cette page, donc qu’à chaque fois que
l’on créé une instance du formulaire jForms, on aille écraser les données en sessions du même formulaire d’un autre
produit ouvert en même temps, on donne un identifiant de formulaire. Ainsi il n’y a pas de collision des données de
chaque instance de formulaire. On peut donner ce que l’on veut comme identifiant (une chaine, un nombre), et en
général on donne l’identifiant de l’enregistrement SQL quand il s’agit de l’édition de ce genre d’information.
En admettant que votre fichier xml soit product.form.php dans le module shop, voici un exemple de création d’un
formulaire pour éditer un produit existant.
$form = jForms::create("shop~product", $product_id);

Bien sûr, quand il s’agit d’afficher un formulaire vierge pour éditer un nouveau produit, il n’y a pas d’identifiant, et
vous n’êtes pas obligé d’en donner un.
$form = jForms::create("shop~product"); // édition d’un nouveau produit

Pour l’exemple précédent avec le formulaire de contact, nous n’indiquons pas d’identifiant, car on émet l’hypo-
thèse ici qu’il s’agit d’un formulaire pour que l’utilisateur envoi une demande de contact : ce sera donc toujours un
formulaire vierge.

15.2.3 Initialisation d’un formulaire

Après la création d’un formulaire, il est peut être nécessaire de le pré-remplir.

Initialisation simple

Pour cela, vous utiliserez la méthode setData sur l’objet formulaire, qui accepte en argument, le nom du champ à
préremplir, et la valeur à lui donner :
$form->setData("prenom","Laurent");

Les valeurs peuvent être récupérées d’ailleurs, comme bon vous semble.

Initialisation avec un dao

Cependant, si vous voulez utiliser un dao, il existe un moyen rapide pour remplir un formulaire. La méthode init-
FromDao() permet d’utiliser un DAO pour remplir plusieurs champs du formulaire. Il suffit d’indiquer à cette méthode
le selecteur du dao à utiliser. Par défaut il prendra la valeur de l’identifiant du formulaire comme identifiant de l’enre-
gistrement à récupérer. Mais vous pouvez indiquer un autre identifiant dans le deuxième argument.
$form = jForms::create("shop~product", $product_id);
$form->initFromDao("shop~products");
Jelix 1.0.6
Guide du développeur
110 / 225

Ici le formulaire sera prérempli avec les valeurs de l’enregistrement dont la clé est $product_id, et le dao "shop~pro-
ducts" sera utilisé pour cette lecture.
Cependant, seuls les champs de saisie qui ont le même nom que des propriétés du dao indiqué seront pré-rempli. Les
autres resteront vides.
Notez que vous pouvez utiliser plusieurs daos pour pré-remplir les champs. En effet on peut avoir besoin d’un
formulaire qui contient des champs de saisie qui seront stockés dans plusieurs tables.

Initialisation d’un champs à choix multiple

Pour les champs <checkboxes> et <listbox multiple="true">, la valeur à initialiser n’est pas forcément une simple
valeur, mais une liste de valeurs qui correspondent à tous les choix qu’il faut pré-sélectionner. (Attention, on parle
bien ici des valeurs présélectionnées, pas de la liste des choix).
On peut donc les initialiser avec setData, en leur passant un tableau contenant les valeurs des choix à présélectionner :
$form->setData(’categories’, array(5, 8, 10));

En général cependant, ces listes de valeurs sont stockées dans une base de données, dans ce qu’on appelle une table
de jointure. C’est à dire une table qui fait la jointure entre deux tables, et dont la clé primaire est constituée de deux clés
étrangères, l’une et l’autre appartenant à une autre table. Par exemple, on a une table pour les produits (’products’),
une table pour les catégories de produits (’categories’), et si un produit peut appartenir à plusieurs catégories, il faut
une table de jointure (’products_categories’), contenant les clés des produits et les clés des catégories qui sont en
relation (product_id et category_id).
Pour initialiser la listbox ou les cases à cocher, il va donc aller lire dans cette table ’products_categories’ les relations.
Il existe pour cela une méthode, initControlFromDao() :
$form->initControlFromDao("categories", "shop~products_categories");

Le dao "shop~products_categories" sera utilisé pour lire les valeurs sélectionnées pour le champs catégories. jForms
s’attend ici à ce que la première clé déclarée dans le dao corresponde à l’identifiant du produit, et la deuxième clé à
l’identifiant des catégories. Si ce n’est pas le cas, il faut alors indiquer les noms de ces clés dans le dao, dans un array
à passer en troisième paramètre :
$form->initControlFromDao("categories", "shop~products_categories", array(’ ←-
product_id’,’category_id’));

Vu qu’il s’agit dans cet exemple de la saisie d’un enregistrement product, et que l’identifiant du formulaire correspond
à l’identifiant du produit, la valeur de cet identifiant sera utilisée comme critère de recherche dans la table, pour
récupérer les id de catégories correspondantes.

Définir les choix d’un champs à multiple choix

Dans le fichier xml jforms, vous avez vu que pour indiquer la liste des choix possibles dans un <menulist>, une
<listbox>, un <radiobuttons> ou un <checkboxes>, vous pouviez indiquer une liste de valeurs statiques, ou un dao
qui servira à récupérer les choix.
Il peut cependant arriver que cela soit insuffisant, et que le remplissage dépende de critères ou autre. Dans ce cas,
vous n’indiquerez pas de balise <item> ni d’attribut dao* dans le fichier xml. Et vous indiquerez la liste des choix
dans votre contrôleur, des manières suivantes.
// récupérez vos données dans un tableau associatif,
$datas = array(...);

// on récupère le contrôle et on lui indique les données


$form->getControl(’nom_du_control’)->datasource->datas = $datas;;
Jelix 1.0.6
Guide du développeur
111 / 225

$datas est un tableau dont les clés sont les valeurs des choix, et les valeurs sont les libellés des choix.
Note : ce remplissage doit se faire dans la même action que celle qui affiche le formulaire. Ces données sont perdues
à la fin de l’action.

15.2.4 Récupérer une instance d’un formulaire

Dans une action spécifique, vous allez créer un formulaire avec jForms : :create(), mais dans d’autres actions, vous
aurez besoin de récupérer le formulaire créé, pour en manipuler ses données. Pour cela il y a deux méthodes statiques
de jForms : get() et fill().
La méthode get() permet de récupérer simplement l’objet formulaire. Comme pour create(), vous indiquez un sélec-
teur :
$form = jForms::get("shop~product");

Si vous aviez donné un identifiant à la création, il faudra le donner aussi ici (récupéré ici à partir des paramètres de
la requête http) :
$product_id = $this->param(’id’);
$form = jForms::get("shop~product", $product_id);

Note : la méthode get renvoie null si le formulaire n’existe pas. Cela veut probablement dire que l’utilisateur a été
à l’url de l’action courante sans passer par les urls de l’action qui a créé le formulaire. Il faudrait alors rediriger vers
ces actions si $form est null. Ou alors créer directement le formulaire, ce qui peut être suffisant pour de simples
formulaires.
$form = jForms::get("main~contact");
if ($form === null) {
$form = jForms::create("main~contact");
}

La méthode fill() récupère aussi le formulaire (c’est à dire appel jForms : :get(), mais exécute aussi une opération
supplémentaire : elle remplie le contenu du formulaire avec les données trouvées en paramètres de la requête HTTP.
En clair, elle est à utiliser lors de la réception du formulaire rempli par l’utilisateur (voir la section plus loin sur
l’utilisation d’un formulaire après submit).
$product_id = $this->param(’id’);
$form = jForms::fill("shop~product", $product_id);

Note : l’identifiant (ici id) doit être actuellement récupéré manuellement avant de récupérer le formulaire, mais il est
prévu dans les versions ultérieures que cela puisse se faire automatiquement.

15.2.5 Gérer un formulaire après submit

Une fois un formulaire créé, il faut, dans une action l’afficher, ce qui est expliqué dans un chapitre à part. Et dans une
autre action, qui sera appelée quand l’utilisateur validera le formulaire, il faudra gérer les données saisies : récupération
des données, vérification de leur contenu et enfin traitement (stockage par exemple).

Remplissage à partir des données saisies

Vous l’avez déjà vu un peu plus haut, pour récupérer l’objet formulaire tout en le remplissant à partir des données
reçues du navigateur, il suffit d’appeler jForms : :fill() :
Jelix 1.0.6
Guide du développeur
112 / 225

$form = jForms::fill("main~contact");

Cela est en fait équivalent à


$form = jForms::get("main~contact");
$form->initFromRequest();

Vous pouvez aussi utiliser la méthode setData sur le formulaire pour remplir vous même le contenu du formulaire :
$form = jForms::get("main~contact");
$form->setData(’nom’, $this->param(’nom’));

Vérification des données

Une fois le formulaire récupéré avec les bonnes données, il est souvent préférable d’en vérifier exactement le contenu
avant de traiter les données. Vous avez à votre disposition la méthode check() qui vérifie les données en fonction de
ce que vous avez indiqué dans le fichier xml (l’aspect obligatoire de la saisie, le type de donnée pour les inputs etc...).
La méthode check() renvoi true si la vérification est bonne, ou false si il y a des erreurs dans le formulaire.
En général, si la validation échoue, vous avez simplement à réafficher le formulaire : les erreurs s’afficheront auto-
matiquement et l’utilisateur devra corriger.
$form = jForms::fill("main~contact");
if (!$form->check()) {
// invalide : on redirige vers l’action d’affichage
$rep = $this->getResponse(’redirect’);
$rep->action=’module~default:show’;
return $rep;
}

Vous pouvez, bien sûr, faire des vérifications approfondies. Vous pouvez alors utiliser la méthode getData pour
récupérer la valeur d’un champ de saisie, et setErrorOn pour indiquer une erreur sur un champ.
$form = jForms::fill("main~contact");
if (!$form->check()) {
// invalide : on redirige vers l’action d’affichage
$rep = $this->getResponse(’redirect’);
$rep->action=’module~default:show’;
return $rep;
}
$ok = true;
$valeur = $form->getData(’nom’);
if( strpos($valeur, ’azerty’) !== null) {
$ok = false;
$form->setErrorOn(’nom’, ’tu as un nom bizarre toi !’);
}
// autres vérifications
//....

if (!$ok) {
// invalide : on redirige vers l’action d’affichage
$rep = $this->getResponse(’redirect’);
$rep->action=’module~default:show’;
return $rep;
}
Jelix 1.0.6
Guide du développeur
113 / 225

Stockage des données

Une fois la vérification faite, vous pouvez extraire les données du formulaire avec la méthode getData() ou getDatas()
(avec un s) qui renvoie toutes les données sous forme de tableau. Ensuite libre à vous d’en faire ce que vous voulez :
les stocker avec jDb ou jDao, les envoyer par mail etc...

Stockage via un dao

Tout comme il y a initFromDao pour initialiser le formulaire, il y a l’opération inverse saveToDao. Cette méthode
permet donc d’enregistrer plusieurs champs via un dao. Les valeurs des champs dont les noms correspondent à des
propriétés du dao indiqué seront utilisées pour renseigner les propriétés du dao correspondantes, et le tout sera en-
registré dans l’enregistrement dont la clé est indiqué dans l’id du formulaire. Si l’id du formulaire est inexistant, un
nouvel enregistrement sera créé, plutôt qu’une mise à jour d’un enregistrement existant.
$form->saveToDao(’shop~products’);

Dans certains cas il peut être utile de récupérer la clé primaire d’un enregistrement créé à l’aide de la méthode
saveToDao.
$primaryKey = $form->saveToDao(’shop~products’);

Stockage des valeurs d’un champ à choix multiples

Il y a la méthode saveControlToDao, qui est l’opération inverse de initControlFromDao. Elle permet donc de sauve-
garder les valeurs sélectionnées d’un ensemble de cases à cocher ou d’une liste à choix multiples, dans une table de
jointure.
$form->saveControlToDao(’categories’, ’shop~products_categories’);

Le premier paramètre est le nom du champ concerné, et le deuxième le dao utilisé pour le stockage.

15.2.6 Stockage des fichiers

Si le formulaire contient des champs de téléchargement de fichiers, il vous faut sauver les fichiers quelque part. Vous
avez pour cela deux méthodes, saveFile() et saveAllFiles. La première pour sauvegarder un fichier précis, et l’autre
pour copier tous les fichiers reçus dans un répertoire. Sachez que dans les données du formulaire, la valeur du champ
(que l’on récupère via getData) contient le nom du fichier original. Si vous avez besoin de stocker un autre nom, faites
un setData.
saveFile() prend en argument le nom du champ contenant le fichier. Par défaut, le fichier est alors stocké dans le
répertoire var/uploads/nommodule~nomform/. Vous pouvez indiquer un autre répertoire en donnant son chemin en
deuxième paramètre de saveFile(). Et si vous voulez stocker le fichier sous un nom différent, indiquez le en troisième
paramètre.
Exemple :
$form->saveFile(’photo’);
$form->saveFile(’photo’, JELIX_APP_WWW_PATH.’images/photos/’);
$form->saveFile(’photo’, JELIX_APP_WWW_PATH.’images/photos/’, $id.’.png’);
$form->saveFile(’photo’, ’’, $id.’.png’);

saveAllFiles sauve tout les fichiers, sans distinction, dans un même répertoire. Le répertoire par défaut est var/u-
ploads/nommodule~nomform/, mais vous pouvez le changer en l’indiquant en paramètre.
$form->saveAllFiles();
$form->saveAllFiles(JELIX_APP_WWW_PATH.’images/photos/’);
Jelix 1.0.6
Guide du développeur
114 / 225

15.2.7 Détruire une instance d’un formulaire

Quand un formulaire n’est plus utilisé (la saisie est finie, les données sauvegardées), il est préférable de faire le
ménage pour ne pas encombrer la session de données inutiles. Il faut donc détruire le formulaire. Pour cela on uti-
lise jForms : :destroy, à laquelle on indique le sélecteur du formulaire, et éventuellement l’identifiant du formulaire
concerné.
jForms::destroy("main~contact");
jForms::destroy(’shop~products’);
jForms::destroy(’shop~products’, $product_id);

15.3 Affichage d’un formulaire

Pour afficher les données d’un formulaire jforms, vous pouvez appeler la méthode getDatas() d’un objet formulaire,
et vous obtiendrez un tableau contenant toutes les données. Vous pouvez passer ensuite ce tableau à un template pour
afficher votre formulaire HTML avec les données. Vous pouvez aussi récupérer les erreurs avec getErrors() et ainsi
afficher les éventuelles erreurs.
Cependant des plugins de templates vous permettent d’éviter de faire ce travail répétitif, et surtout font bien plus
qu’afficher les valeurs :
– affichage de chaque champ de saisie, en accord avec ce qui est décrit dans le fichier XML du formulaire,
– affichage des libellés de chaque champ dans des balises <label> pour une meilleure ergonomie/accessibilité,
– affichage automatique des messages d’erreurs,
– affichage des messages d’aide,
– intégration du code javascript qui vérifiera le bon contenu des données saisies avant validation du formulaire,
– code HTML généré valide, avec un effort sur l’accessibilité,
– des classes sur les balises générés pour pouvoir les styler facilement.

15.3.1 Affichage sans personnalisation

Pour les développeurs pressés, il existe un plugin de template qui affiche tout tout seul : formfull. Vous ne pouvez
pas contrôler la façon dont sont affichés les champs de saisie, leur libellés et les boutons de validation. La seule chose
que vous pouvez personnaliser c’est l’affichage des messages d’erreurs et d’aide (voir plus loin).
Vous devez passer à ce plugin, les paramètres suivant :
– l’objet formulaire
– le selecteur de l’action où le contenu du formulaire sera envoyé
– facultatif : les paramètres de l’url de cette action (autre que les champs de saisie)
Voici un exemple dans le contrôleur :
$form = jForms::get(’monform’);
$tpl = new jTpl();
$tpl->assign(’formulaire’, $form);

Attention, jForms : :get retourne une instance du formulaire ayant déjà été créée. Si elle n’a jamais été créée, vous
devez la générer :
if (! $form = jForms::get(’monform’)) {
$form = jForms::create(’monform’);
}

Et dans le template :
Jelix 1.0.6
Guide du développeur
115 / 225

<h1>Le formulaire</h1>
<p>Remplissez le formulaire suivant :</p>

{formfull $formulaire, ’monmodule~default:sauver’}

Les libellés et les champs de saisies s’affichent dans un tableau, et les boutons de validation dans une div en dessous
du tableau.

15.3.2 Affichage contrôlé

D’autres plugins que formfull existent permettant de mieux contrôler l’affichage des champs de saisie, en particulier,
de pouvoir définir les endroits où les champs seront placés.
Le premier plugin à connaître, est le plugin form. Il a les même paramètres que formfull. C’est un plugin de type
bloc, c’est à dire qu’il y a une balise de fin, et qu’entre les deux balises form, on y placera les autres plugins.

affichage contrôlé simple

Le plugin formcontrols permet de faire une boucle sur la liste des champs de saisie. C’est aussi un bloc dans lequel
on utilisera les plugins ctrl_label et ctrl_control pour afficher respectivement le libellé et le champs de saisie. Et on
utilise le plugin formsubmit pour afficher le bouton de validation déclaré dans le fichier xml, ainsi que formreset pour
afficher le bouton reset si il est déclaré lui aussi dans le fichier xml.
Exemple :
{form $formulaire, ’monmodule~default:sauver’}

<fieldset><legend>Saisissez : </legend>

{formcontrols}
<p> {ctrl_label} : {ctrl_control} </p>
{/formcontrols}

</fieldset>

<div> {formreset}{formsubmit} </div>

{/form}

Notez que les champs seront affiché dans le même ordre que leur déclaration dans le fichier XML. Notez également
qu’ici le template est totalement indépendant du contenu du formulaire. Il pourrait être réutilisé avec plusieurs
formulaires.

aller plus loin dans le contrôle de l’affichage

Il arrive que l’on ne veuille pas présenter tout les champs de saisie de la même façon. On peut alors indiquer une
liste des noms des champs à afficher au plugin formcontrols.
{form $formulaire, ’monmodule~default:sauver’}

<fieldset><legend>Votre identité : </legend>

{formcontrols array(’nom’,’prenom’,’adresse’)}
Jelix 1.0.6
Guide du développeur
116 / 225

<p> {ctrl_label} : {ctrl_control} </p>


{/formcontrols}

</fieldset>
<fieldset><legend>Autres renseignements : </legend>

{formcontrols}
<p> {ctrl_label} : {ctrl_control} </p>
{/formcontrols}

</fieldset>

<div> {formsubmit} </div>


{/form}

Dans cet exemple, on affiche une première série de champs de saisie (les champs nom, prenom et adresse). Et une
deuxième série dont on ne précise pas la liste de champs : formcontrols bouclera alors uniquement sur les champs qui
n’ont pas encore été affiché.
Vous pouvez aussi utiliser ctrl_label et ctrl_control en dehors d’une boucle formcontrols. Vous devez alors leur
indiquer un nom de champs.
{form $formulaire, ’monmodule~default:sauver’}
<fieldset><legend>Votre identité : </legend>
<table>
<tr><td>{ctrl_label ’nom’}</td><td>{ctrl_control ’nom’}</td> </tr>
<tr><td>{ctrl_label ’prenom’}</td><td>{ctrl_control ’prenom’}</td></tr>
</table>
</fieldset>
<fieldset><legend>Autres renseignements : </legend>
{formcontrols}
<p> {ctrl_label} : {ctrl_control} </p>
{/formcontrols}
</fieldset>
<div> {formsubmit} </div>
{/form}

Ici on affiche les champs noms et prenoms à des endroits précis, et le reste sera affiché par le plugin formcontrols
qui suit.

contrôle de l’affichage des champs de type password

Pour les champs de saisie de mot de passe pour lesquels il y a un champ de confirmation (balise confirm), si vous
indiquez explicitement leur affichage, il faut aussi indiquer spécifiquement l’affichage du champs de confirmation,
sachant que celui-ci a le nom du champs de saisie principale avec un suffixe _confirm.
Par exemple, vous indiquez explicitement d’afficher le champs "motdepasse" qui est un mot de passe :
{form $formulaire, ’monmodule~default:sauver’}
<fieldset><legend>Créer votre compte : </legend>
<table>
<tr><td>{ctrl_label ’login’}</td><td>{ctrl_control ’login’}</td> </tr>
<tr><td>{ctrl_label ’motdepasse’}</td><td>{ctrl_control ’motdepasse’}</ ←-
td></tr>
</table>
</fieldset>
Jelix 1.0.6
Guide du développeur
117 / 225

<fieldset><legend>Autres renseignements : </legend>


{formcontrols}
<p> {ctrl_label} : {ctrl_control} </p>
{/formcontrols}
</fieldset>
<div> {formsubmit} </div>
{/form}

Ici, si le champs de confirmation ne s’affichera pas prés du champs de mot de passe. Il faut donc rajouter le champs
"motdepasse_confirm" :
<table>
<tr><td>{ctrl_label ’login’}</td><td>{ctrl_control ’login’}</td> </tr>
<tr><td>{ctrl_label ’motdepasse’}</td><td>{ctrl_control ’motdepasse’}</td></ ←-
tr>
<tr><td>{ctrl_label ’motdepasse_confirm’}</td><td>{ctrl_control ’ ←-
motdepasse_confirm’}</td></tr>
</table>

Par contre, il n’est pas besoin de préciser le champs de confirmation quand on afficher le champs de saisie de mot de
passe dans une boucle formcontrols.

contrôle de l’affichage des boutons d’envoi

On a vu que l’on pouvait utiliser le plugin formsubmit pour afficher le bouton d’envoi déclaré dans votre formulaire.
Mais utilisé comme cela, si vous avez déclaré plusieurs balises submit, seule le premier bouton sera affiché. Dans ce
cas là il faut utiliser le plugin formsubmits (avec un s), qui est une boucle sur les boutons d’envoi :
<ul>
{formsubmits}
<li>{formsubmit}</li>
{/formsubmits}
</ul>

Ou encore, vous pouvez utiliser plusieurs plugins formsubmit, sans formsubmits, en indiquant le nom du bouton :
<div> {formsubmit ’preview’} {formsubmit ’save’} </div>

– *Attention** : {formsubmits} boucle sur la liste des contrôles submit, pas sur les item d’un submit ! Il n’est pas
possible pour le moment de boucler sur les items d’un submit (voir ticket #429)

15.3.3 Classes CSS à connaître

Pour styler les balises générées par jForms, il y a quelques classes de style à connaître (certaines de ces classes ont
été ajoutée dans la version 1.0.1).
– jforms-table : c’est la classe du tableau généré par le plugin formfull
– jforms-submit-buttons : c’est la classe de la div générée par le plugin formfull, contenant les boutons d’envois.
– jforms-submit : classe sur chaque bouton submit
– jforms-reset : classe sur chaque bouton reset
– jforms-error-list : classe de la liste (ul) des messages d’erreurs.
– jforms-label : classe placée sur toutes les balises <label>
– jforms-required : classe placée sur toutes les balises <label> dont les champs sont obligatoires
– jforms-error : classe placée sur toutes les balises <label> et sur les champs de saisies qui sont en erreur
– jforms-value : classe sur les élements span contenant les valeurs des champs de type output.
Jelix 1.0.6
Guide du développeur
118 / 225

– jforms-help : classe placée sur les élements span contenant les liens d’aide.
– jforms-chkbox : classe placée sur le span qui entoure chaque checkbox d’un controle checkboxes.
– jforms-ctl-xxx : classe placée sur chaque checkbox d’un controle checkboxes, ou chaque boutons radio d’un
contrôle radiobuttons (xxx étant remplacé par le ref du controle).
– jforms-radio : classe placée sur le span qui entoure boutons radio d’un contrôle radiobuttons.

15.3.4 Utilisation de jforms dans des réponses Ajax

Voir la note sur la page des réponses ajax

15.3.5 Personnalisation de l’affichage des messages

Les messages d’erreurs, qui peuvent survenir lors de la vérification du formulaire avant l’envoi des données, et les
messages d’aides qui apparaissent quand on clique sur le point d’interrogation , sont affiché dans une boite de dialogue
de type alert.
Vous pouvez changer ça, en fournissant aux plugins form ou formfull des objets javascript qui s’occuperont d’afficher
ces messages.

Affichage des messages d’erreurs

Pour les messages d’erreurs, il faut créer un objet javascript qui contient trois méthodes :
– start, qui est appelé quand le processus de vérification commence
– addError, qui est appelé quand une erreur est trouvée. Cette méthode reçoit un objet javascript jFormsControl qui
contient des données relatifs au champs de saisie en faute, et un code erreur : 1 si le champs n’est pas renseigné
alors qu’il est obligatoire, et 2 si le contenu saisi est invalide.
– end, qui est appelé quand le processus de vérification est terminé
Dans ces méthodes vous faites ce que vous voulez. Par exemple, dans addError, vous pouvez insérer dans une liste
html le message d’erreur, comme dans l’exemple (l’élément "errors" est une liste <ul> quelque part dans votre page
html) :
function MyErrorDecorator(){
}

MyErrorDecorator.prototype = {
start : function(){
},
addError : function(control, messageType){
var message=’’;
if(messageType == 1){
message = control.errRequired;
}else if(messageType == 2){
message = control.errInvalid;
}else{
message = "Error on ’"+control.label+"’ field";
}
var item = document.createElement("li");
item.appendChild(document.createTextNode(message));
document.getElementById("errors").appendChild(item);
},
end : function(){
}
}
Jelix 1.0.6
Guide du développeur
119 / 225

Ensuite vous l’indiquez au plugin form ou formfull, en 4ième argument :


{form $formulaire, ’monmodule~default:sauver’, array(), "MyErrorDecorator"}
...
{/form}

En ce qui concerne l’objet jFormsControl que addError reçoit en paramètre (ici control), voici les propriétés utiles
qu’il contient :
– name : le nom du contrôle, du champs de saisie
– label : son libellé
– datatype : type de donnée (attribut type pour les input dans le fichier xml)
– required : booléen indiquant si il est obligatoire
– readonly : booléen indiquant si il est en lecture seule
– errInvalid : message d’erreur prédéfini quand son contenu est invalide
– errRequired : message d’erreur prédéfini quand le champs n’est pas renseigné
– help : message d’aide

Affichage des messages d’aides

Pour les messages d’aide, c’est le même principe que pour les messages d’erreur, mais l’objet ne doit contenir qu’une
méthode, show qui est appelé avec en paramètre le message affiché.
function MyHelpDecorator(){ }

MyHelpDecorator.prototype = {
show : function(message){
document.getElementById("help").firstChild = document.createTextNode( ←-
message);
}
}

Ensuite il faut indiquer cet objet en 5ième argument de form ou formfull :


{form $formulaire, ’monmodule~default:sauver’, array(), "", "MyHelpDecorator"}
...
{/form}

Notez ici que l’on a indiqué "" pour l’affichage des erreurs : jforms utilisera alors l’afficheur par défaut. Mais vous
pouvez aussi indiquer un autre, en même temps que l’afficheur d’aide.

15.4 Affichage simple des données

Il est possible d’afficher, non pas le formulaire en lui même, mais seulement les données du formulaire. Cela peut
être utile pour afficher le récapitulatif des données saisies par exemple.

15.4.1 Affichage sans personnalisation

Pour les développeurs pressés, il existe un plugin de template qui affiche tout tout seul : formdatafull. Vous ne
pouvez pas contrôler la façon dont sont affichés les libellés et les valeurs. Vous devez passer l’objet formulaire à ce
plugin.
Voici un exemple dans le contrôleur :
Jelix 1.0.6
Guide du développeur
120 / 225

$form = jForms::get(’monform’);
$tpl = new jTpl();
$tpl->assign(’formulaire’, $form);

Et dans le template :
<h1>Le formulaire</h1>
<p>Vous avez saisie les valeurs suivantes:</p>

{formdatafull $formulaire}

Les libellés et les valeurs du formulaires s’affichent dans un tableau.


Note : vous pouvez utiliser formdatafull dans un template pour une réponse text.

15.4.2 Affichage contrôlé

Comme pour l’affichage du formulaire, il est possible de mieux contrôler l’affichage, en particulier les balises géné-
rées, et donc de pouvoir définir les endroits où les champs seront placés.
Vous pouvez utiliser les plugins {formcontrols} et {ctrl_label} que vous connaissez déjà, ainsi que {ctrl_value} :
<h1>Le formulaire</h1>
<p>Vous avez saisie les valeurs suivantes:</p>

<table>
{formcontrols $formulaire}
<tr>
<th scope="row">{ctrl_label}</th>
<td>{ctrl_value}</td>
</tr>
{/formcontrols}
</table>

Notez que vous n’avez pas besoin d’utiliser le plugin {form}.


Il est possible aussi de ne pas utiliser la boucle {formcontrols}, afin d’afficher les valeurs où on veut et dans l’ordre
que l’on souhaite, avec toujours les plugins {ctrl_label} et {ctrl_value} en leur indiquant le nom du contrôle à afficher.
Mais il faut alors les utiliser à l’intérieur d’un plugin {formdata}
<h1>Le formulaire</h1>
<p>Vous avez saisi les valeurs suivantes :</p>

<table>
{formdata $formulaire}
<tr>
<th>{ctrl_label ’name’}</th>
<td>{ctrl_value ’name’}</td>
</tr>
<tr>
<th>{ctrl_label ’address’}</th>
<td>{ctrl_value ’address’}</td>
</tr>
{/formdata}
</table>
Jelix 1.0.6
Guide du développeur
121 / 225

Chapitre 16

jDb : accéder à une base de données

Jelix possède un système d’accès abstrait aux bases de données : jDb. jDb propose donc une API commune à toutes
les bases de données. Pour le moment, les drivers fournis sont ceux pour :
– mysql
– postgresql
– sqlite
Il y a aussi un autre driver, pdo, permettant d’indiquer à jDb d’utiliser pdo plutôt que les classes d’abstractions
internes de jDb. Il est d’ailleurs recommandé d’utiliser pdo pour des raisons de performances.
Si dans la liste ci-dessus, il n’y a pas le driver correspondant à votre base de donnée et que vous n’avez pas PDO,
vous pouvez créer votre propre driver pour jDb.
À noter que bien que jDb soit une API commune à toutes les bases de données, ce n’est en aucun cas pas une classe
qui adaptera les requêtes en fonction des bases de données. Aussi, faites attention à ne pas trop utiliser des spécificités
SQL d’une base de donnée précises dans vos modules, si vous souhaitez qu’il puisse être réutilisé dans d’autres projets
qui n’utiliseront pas la même base.

16.1 Profils et configuration

Pour pouvoir accéder à une base de données, il faut d’abord indiquer les paramètres de connexion dans un fichier de
configuration. Ce fichier est par défaut dbprofils.ini.php situé dans var/config/. Vous pouvez en avoir un avec un nom
différent, il faut alors indiquer ce nom dans le fichier de configuration principal de votre application.
Vous pouvez définir plusieurs connexions, que l’on nomme "profiles". Ainsi vous pouvez définir des connexions pour
la base de production, la base de développement par exemple, ou encore les différentes bases sur lesquelles s’appuie
votre application.
Voici un exemple de fichier dbprofils.ini.php :
default = foo

[foo]
driver="mysql"
database="jelix"
host= "localhost"
user= "jelix"
password= "jelix"
persistent= on
force_encoding=true
Jelix 1.0.6
Guide du développeur
122 / 225

Il y a une section "foo". Chaque section correspond à un profil de connexion. Un paramètre, "default", indique le
profil à utiliser par défaut.
Dans une section, vous voyez un certain nombre de paramètres, dont quelques-un sont utilisables pour tout les
drivers :
– driver indique le driver a utilisé. Le nombre et le nom des autres paramètres diffèrent en fonction du driver utilisé.
– table_prefix : permet d’indiquer un préfixe de table. Lors de l’utilisation d’un DAO avec un profil spécifiant ce
paramètre, les tables indiquées dans le DAO sont préfixées dynamiquement par cette valeur. Lors de l’écriture
manuelle de requêtes pour jDb, vous pouvez préfixer vos tables en fonction du profil utilisé grâce à la méthode
prefixTable() de jDbConnection. Cette méthode prend en paramètre le nom de la table à préfixer.

16.1.1 profil mysql

Paramètres possibles :
– driver : doit valoir "mysql"
– database : le nom de la base de donnée à utiliser
– host : le nom du serveur mysql sur lequel se connecter
– user et password : le login/mot de passe pour la connexion
– persistent : indique si la connexion est persistante (on) ou pas (off)
– force_encoding : indique si il faut spécifier le charset utilisé dans l’application, de manière à récupérer les données
avec le bon charset. En effet, certains serveur sont configurés par exemple par défaut avec une connexion en iso-
8859-1, même si les données stockées sont en utf-8. Mettez à true si vous voyez que vous n’arrivez pas à afficher
les données correctement.

16.1.2 profil postgresql

Paramètres possibles :
– driver : doit valoir "pgsql"
– database : le nom de la base de donnée à utiliser
– host : le nom du serveur postgresql sur lequel se connecter. Si vous le mettez à vide, la connexion se fera via une
socket unix.
– port : indique le port de connexion. N’indiquez pas ce paramètre si vous voulez utiliser le port par défaut.
– user et password : le login/mot de passe pour la connexion. Ne mettez pas ces paramètres si vous voulez utiliser
le login/mot de passe par défaut (indiqués par exemple dans les variables d’environnement du système).
– persistent : indique si la connexion est persistante (on) ou pas (off)
– force_encoding : indique si il faut spécifier le charset utilisé dans l’application, de manière à récupérer les données
avec le bon charset. même explication que pour mysql.
– timeout : Nombre de seconde autorisées pour l’établissement de la connexion au serveur avant de générer un
timeout
– single_transaction : Toutes les requêtes d’une même page seront envoyées au serveur au sein d’un même tran-
saction (entre un BEGIN ; et un COMMIT ;) (on) ou non (off). Défaut : off

16.1.3 profil sqlite

Paramètres possibles :
– driver : doit valoir "sqlite"
– database : le nom du fichier de base de donnée à utiliser
– persistent : indique si la connexion est persistante (on) ou pas (off)
A noter que les fichiers de base de données sqlite doivent être déposés dans le répertoire : var/db/sqlite/ de votre
application et qu’à la fois ce répertoire et le fichier de base de données sqlite doivent avoir les droits de lecture/écriture
adéquats (ceux du serveur web).
Jelix 1.0.6
Guide du développeur
123 / 225

16.1.4 profil pdo

Paramètres possibles :
– driver : doit valoir "pdo"
– dsn : contient des informations de connexion (type de base de donnée, serveur, nom de la base..). Le format doit
être celui attendu par PDO (voir la doc de pdo sur php.net).
– user et password : le login/mot de passe pour la connexion. Ne mettre ces paramètres que si nécessaire.
– force_encoding : indique si il faut spécifier le charset utilisé dans l’application, de manière à récupérer les données
avec le bon charset. même explication que pour mysql, et ce paramètre n’est pour le moment valable que pour
mysql et postgresql.
[bar]
driver=pdo
dsn= "mysql:host=localhost;dbname=test"
user=
password=

16.2 Faire des requêtes

Une fois le fichier de configuration écrit, vous pouvez accéder aux bases de données.
La première chose à faire est de récupérer un objet jDbConnection :
$cnx = jDb::getConnection();

La méthode getConnection() permet de récupérer un objet de type jDbConnection (ou jDbPDOConnection héritant
de PDO, si vous utilisez PDO, ils ont toutefois la même API). Cette méthode accepte un paramètre facultatif : le nom
du profil à utiliser. Si il n’est pas indiqué, celui déclaré par défaut sera utilisé.
Pour construire les requêtes, vous avez une méthode importante à connaître : quote(), qui permet d’échapper cer-
tains caractères dans les valeurs que vous voulez insérer dans vos requêtes. Elle évite dans une certaine mesure les
problèmes comme l’injection SQL.
$sql = "INSERT INTO users (nom,prenom) VALUES";
$sql .=" (". $cnx->quote("de l’ombre") .",".$cnx->quote(’robert’).")";

Notez que la méthode quote() encadre la valeur avec des quotes.


Pour exécuter des requêtes, il y a principalement deux méthodes, exec et query.

16.2.1 exec

exec doit être utilisé pour les requêtes qui ne renvoient pas de résultat (UPDATE, INSERT, DELETE...). cette mé-
thode renvoi juste le nombre de lignes concernées par la requête. Exemple :
$cnx = jDb::getConnection();

$cnx->exec("INSERT INTO users (nom,prenom) VALUES(’dupont’,’toto’)");

16.2.2 query

query est fait pour les requêtes qui renvoient des résultats, vides ou pas (SELECT ou procédures stockées). La
méthode renvoi alors un objet jDbResultSet.
Voici un exemple rapide :
Jelix 1.0.6
Guide du développeur
124 / 225

$cnx = jDb::getConnection();

$rs = $cnx->query(’SELECT nom, prenom FROM users’);


$result=’’;
while($record = $rs->fetch()){
$result.=’nom = ’.$record->nom.’ prenom=’.$record->prenom."\n";
}

16.2.3 limitQuery

Vous pouvez faire des requêtes qui récupèrent un nombre limité d’enregistrement. Vous utiliserez alors la méthode
limitQuery :
$cnx = jDb::getConnection();

$rs = $cnx->limitQuery(’SELECT nom, prenom FROM users’, 5,10);


$result=’’;
while($record = $rs->fetch()){
$result.=’nom = ’.$record->nom.’ prenom=’.$record->prenom."\n";
}

Le premier paramètre est la requête. Le deuxième est le numéro, dans la liste des résultats, du premier enregistrement
à récupérer. Le troisième paramètre est le nombre d’enregistrements à récupérer.

16.3 ResultSet

jDbResultSet est l’objet que vous récupérez après avoir fait un SELECT (query ou limitQuery).
Sa méthode fetch() vous permet de récupérer un à un les enregistrements. À noter que jDbResultSet renvoie toujours
un enregistrement sous forme d’objet.
Sa méthode fetchAll() permet de récupérer tout d’un coup dans un tableau PHP.
jDbResultSet implémente l’interface Iterator. De ce fait, vous pouvez utiliser cet objet dans certaines boucles, comme
les foreach :
$cnx = jDb::getConnection();

$rs = $cnx->query(’SELECT nom, prenom FROM users’);


$result=’’;
foreach( $rs as $record){
$result.=’nom = ’.$record->nom.’ prenom=’.$record->prenom."\n";
}

Les objets contenant les enregistrements sont des objets "anonymes" (ils n’ont pas de classe précise). Si vous voulez
que ce soit des objets d’une certaine classe, vous devez l’indiquer via setFetchMode :
class User {
...
}

$cnx = jDb::getConnection();

$rs = $cnx->query(’SELECT nom, prenom FROM users’);


$rs->setFetchMode($rs->FETCH_CLASS , ’User’);
Jelix 1.0.6
Guide du développeur
125 / 225

$result=’’;
foreach( $rs as $record){
// $record est ici un objet de type User
$result.=’nom = ’.$record->nom.’ prenom=’.$record->prenom."\n";
}

Pour le reste des méthodes, voyez la documentation de référence.

16.3.1 Utilisation dans un template

Il est possible de passer un objet jDbResultSet dans un template.


Dans le contrôleur :
$cnx = jDb::getConnection();

$rs = $cnx->query(’SELECT nom, prenom FROM users’);

$template->assign(’resultats’, $rs);

Dans le template :
<table>
<tr> <th>nom</th> <th>prenom</th></tr>
{foreach $resultats as $user}
<tr>
<td>{$user->nom|eschtml}</td>
<td>{$user->prenom|eschtml}</td>
</tr>
{/foreach}
</table>

16.4 Transactions

jDb permet de faire des transactions. Bien sûr, il faut que le driver utilisé supporte les transactions.
Pour marquer le début d’une transaction, vous appelerez la méthode beginTransaction (). Ensuite vous lancerez les
requêtes, Puis aprés avoir fait vos requêtes, vous pourrez valider la transaction en appelant la méthode commit(). Pour
annuler une transaction, il suffit d’appeler rollback().
$cnx = jDb::getConnection();

$cnx->beginTransaction();

$cnx->exec(...);
$cnx->query(...);
//....

if($ok)
$cnx->commit();
else
$cnx->rollback();
Jelix 1.0.6
Guide du développeur
126 / 225

16.5 jDbWidget

jDbWidget est une classe fournissant des méthodes utiles.


$dbw = jDb::getDbWidget(); // au lieu de getConnection()

$record = $dbw->fetchFirst("SELECT nom, prenom FROM user");

$liste = $dbw->fetchAll("SELECT nom, prenom FROM user");

Pour le reste des méthodes, voyez la documentation de référence.


Jelix 1.0.6
Guide du développeur
127 / 225

Chapitre 17

jClasses : utiliser des classes métiers

Pour respecter le modèle en couche, il est recommandé de réaliser tout ses traitements métiers et services dans des
classes dédiées.
Dans de telles classes, vous manipulerez par exemple des daos, des données issues de daos ou autre, effectuerez
donc des traitements autres que de l’affichage. Aussi les méthodes de vos controllers s’en trouveront allégées et les
traitements réutilisables dans d’autres actions.

17.1 Création d’une classe

Les classes métiers et services dans Jelix sont des classes PHP classiques qui n’ont rien de spécifique. La seule chose
à respecter est de la stocker dans un fichier nom_de_la_classe.class.php dans le répertoire classes du module :
class StockService {
public function getListeProduits(){
$stock = jDAO::get("products");

$liste = $stock->findAll();

// ici traitement sur la liste... par exemple

return $liste;
}
}

Cette classe devra être stockée dans classes/StockService.class.php.


La différence entre une classe service avec les autres classes est qu’une classe service fourni comme son nom l’in-
dique, un service. Elle n’a pas besoin d’être instanciée à chaque utilisation car elle ne possède pas de propriétés
"discriminantes". Une seule instance suffit pour toute l’application.
Par exemple une classe de type "factory", qui permet de récupérer des ensembles de données, est une classe service.
Par contre une classe représentant un produit, qui possède donc des champs identifiants, est une classe non service.

17.2 Instanciation

Jelix propose la classe jClasses, qui vous évite d’avoir à faire un include et une instanciation par vous même.
jClasses fournit deux méthodes statiques, auxquelles vous indiquez un sélecteur :
Jelix 1.0.6
Guide du développeur
128 / 225

– createInstance($selecteurDeClasse) ; (ou create($selecteurDeClasse) )


– getService($selecteurDeClasse) ;
La première créera à chaque appel une nouvelle instance. Par contre la deuxième renverra toujours une même instance
de la classe. getService sera donc utilisé sur les classes services, et createInstance sur les autres.
Si notre classe StockService se trouve dans le module "shop", voici un exemple d’appel dans un contrôleur :
$stocksrv = jClasses::getService("shop~stockservice");
$rep->body->assign(’liste_produits’, $stocksrv->getListeProduits());

Cependant dans certains cas, comme celui où le constructeur de la classe métier demande un paramètre, il faut inclure
la classe métier puis l’instancier "manuellement".
Dans ce cas la classe jClasses propose la méthode statique inc($selecteurDeClasse). Comme son nom l’indique elle
inclue (en fait effectue un require_once) la classe spécifiée par le sélecteur.
Exemple :
jClasses::inc(’shop~shoesProduct’);
$shoe = new shoesProduct(’43’, ’black’);

Notez que vous pouvez mettre des classes dans des sous-repertoires de "classes/", ce qui donne, si on place Stock-
Service dans un répertoire classes/stocks/ :
$stocksrv = jClasses::getService("shop~stocks/stockservice");

17.3 Installer et Utiliser des classes tierces

Il se peut que vous vouliez réutiliser des classes développées en dehors du projet. Il est bien entendu tout à fait
possible de le faire dans Jelix.
Bien que vous puissiez mettre ces classes où bon vous semble et faire un include classique, il y a toutefois deux
emplacements préconisés :
– le répertoire lib
– le répertoire classes d’un module
Faire un répertoire spécifique dans lib/ et y placer les fichiers de classes, est interessant quand il s’agit de partager ces
classes entre plusieurs modules, voire entre plusieurs projets. Pour faire les includes, vous pouvez utiliser la constante
LIB_PATH. Par exemple si vous voulez inclure une classe que vous avez dans lib/foo/bar.php, vous ferez alors ceci :
require(LIB_PATH.’foo/bar.php’);
$maclasse = new bar();

Placer les classes tierces dans le répertoire classes, est utile si les classes en question ne sont utilisées que par ce
module. Cela permet aussi une réutilisation plus facile : tout est dans le module.
Pour utiliser ces classes, en admettant que vous voulez inclure le fichier bar.php que vous avez placé dans le répertoire
classes du module main, vous pouvez faire :
require(JELIX_APP_PATH.’modules/main/classes/bar.php’);
$maclasse = new bar();

Si le nom du fichier de la classe respecte la norme des fichiers de classes pour jelix (bar.class.php), et que la classe
s’appelle effectivement "bar", vous pouvez bien entendu utiliser jClasses :
$maclasse = jClasses::create(’bar’);

// ou si le constructeur attend des arguments


jClasses::inc(’bar’);
$maclasse = new bar(’bla’);
Jelix 1.0.6
Guide du développeur
129 / 225

Chapitre 18

jUrl : des URLs automatiques

Jelix comporte un mécanisme qui permet de ne pas avoir à mettre les URLs concernant les actions en dur dans les
templates (ou ailleurs). Pour faire simple, il suffit de fournir le module, l’action, le type de requête et éventuellement
d’autres paramètres et jUrl se charge de générer l’URL correspondante. À l’inverse, lors d’une requête, jUrl analyse
l’URL pour en déduire le module, l’action et les paramètres, et ceci, indépendamment du type de requête. Il n’est pas
utile alors d’utiliser le mod_rewrite d’apache.
Pour cette tâche jUrl se repose sur un moteur d’URL. Il y en a deux fournis dans Jelix :
– un moteur d’URL simple (utilisé par défaut)
– un moteur d’URL significatifs
Sachez que vous pouvez créer votre propre moteur d’URLs pour des besoins plus spécifiques.

18.1 Petit rappel sur les URLs

Une URL est composée de différentes parties :

http://monsite.com/un/chemin/pointentree.php/path/info?param1=value1

– un/chemin/pointentree correspond au chemin du point d’entrée : /index par exemple


– .php l’extension du point d’entrée. Elle est facultative si le multiview est activé dans apache
– /path/info le pathinfo, partie complémentaire du chemin, ne correspondant pas à un chemin physique sur le disque.
– ?param1=value1 : les paramètres.
Les moteurs d’URLs analysent le pathinfo et les paramètres pour déterminer le module/action
Note : il peut y avoir certaines options à activer dans apache. Voir la page installation

18.2 Configuration générale

La configuration de jUrl se fait dans la section urlengine du fichier de configuration dont voici les paramètres :

18.2.1 engine

Indique le type de moteur à utiliser. Les deux valeurs disponibles sont simple et significant.
Jelix 1.0.6
Guide du développeur
130 / 225

18.2.2 enableParser

Active l’analyse d’URL par le moteur d’URL. Si vous préférez l’utilisation du module mod_rewrite d’apache, vous
pouvez alors mettre off.

18.2.3 multiview

Indique si le multiview est activé ou non dans apache. Cela indique alors au moteur d’URL de ne pas générer
l’extension des points d’entrées (.php) lors de la création des URLs. On a ainsi des URLs un peu plus "propres".

18.2.4 basePath

Chemin jusqu’au répertoire www, ou plutôt, la partie commune des chemins de tous les points d’entrée.
Ainsi, si vous accédez à index.php avec l’URL http ://localhost/jelix/myapp/www/index.php, alors vous indiquez

basePath= /jelix/myapp/www/

Si par contre vous avez spécifié le documentRoot dans apache, pointant sur jelix/myapp/www, alors vous indiquerez

basePath= /

Attention, la valeur de basePath doit toujours commencer par un /.


Si vous n’indiquez aucune valeur, Jelix essaiera de deviner le chemin de base par lui même.

18.2.5 defaultEntrypoint

Point d’entrée par défaut de l’application. index par défaut. Vous ne devez pas indiquer le suffixe (.php).

18.2.6 entrypointExtension

Extensions des points d’entrées. Par défaut, c’est .php, mais peut-être que sur votre serveur, pour utiliser PHP5 il
vous faille utiliser l’extension .php5 par exemple. Auquel cas vous indiquerez .php5.

18.2.7 notfoundAct

L’action à effectuer quand une URL ne correspond à rien. Indiquez là sous forme de sélecteur d’action : "module-
~action". L’action indiquée devra correspondre à l’affichage d’une page d’erreur par exemple et renvoyer le code http
404.
Attention ! Quand vous êtes en développement, il est recommandé de ne rien mettre dans ce paramètre. Ainsi ce sera
plus facile à debogger car en cas d’appel d’une module/action inconnue vous aurez un message d’erreur de la part de
Jelix qui sera plus explicite qu’une simple page 404.
Jelix 1.0.6
Guide du développeur
131 / 225

18.3 Configuration des moteur d’URLs

En standard Jelix fournis deux moteurs d’URLs :


– Le moteur "simple", qui est performant mais qui ne permet pas d’avoir des URLs "cools"
– Le moteur "significant", qui permet d’avoir les URLs que vous voulez, bien qu’il soit un peu moins performant.
Aller donc lire les pages qui leurs sont dédiées pour les configurer correctement :
– Moteur "simple"
– Moteur "significant"

18.4 Utilisation

Vous devez éviter de mettre des URLs en dur dans votre code, dans vos modules. Sinon cela crée des dépendances
et la portabilité de vos modules s’en trouve diminuée. Il est impossible alors d’utiliser le module pour plusieurs
applications en même temps car les URLs peuvent être différentes en fonction de la configuration des applications. Et
si le module est réutilisé ailleurs, il faudrait alors modifier les templates etc...
De plus, faire générer les URLs par Jelix vous permet de changer à loisir le moteur d’URLs ou sa configuration, sans
avoir à changer quoi que ce soit dans vos templates et vos contrôleurs.
Les URLs doivent donc être construites par Jelix. Pour cela, vous avez deux outils à votre disposition.

18.4.1 jUrl : :get

L’objet jUrl a une méthode statique, get(), qui en fonction d’une action et d’autres paramètres, renvoie l’URL cor-
respondante pour l’application courante :
$string_url = jUrl::get("news~view@classic", array("id_news"=>"54"));

Le premier paramètre de la fonction est donc un sélecteur d’action. Ici on demande l’URL qui correspond à l’action
view du module news, pour le type de requête classic avec un paramètre id_news. Avec le moteur d’URL simple,
l’URL correspondante sera probablement index.php ?module=news&action=view&id_news=54.
Si le moteur d’URL significant est utilisé, cela peut être n’importe quoi d’autre, en fonction de ce qui est configuré
dans le fichier urls.xml.

18.4.2 Plugin de template jurl

Dans les templates vous pouvez utiliser le plugin jurl. Sa syntaxe est identique à jUrl : :get(). Exemple :
<p><a href="{jurl ’news~view@classic’, array(’id_news’=>’54’)}">Détails de la ←-
news</a></p>

Le résultat avec le moteur d’URL simple sera alors :


<p><a href="index.php?module=news&amp;action=view&amp;id_news=54">Détails de la ←-
news</a></p>

18.5 Moteur d’urls ’simple’

Ce moteur est celui activé par défaut. Toutes les URLs ressembleront à pointentree.php ?module=..&action=...&...
. C’est un moteur qui est donc très simple et performant. Son principal inconvénient si on peut dire, c’est qu’avec lui,
les URLs ne sont pas très "jolies".
Jelix 1.0.6
Guide du développeur
132 / 225

18.5.1 Configuration

Si vous utilisez les points d’entrées fournis en standard vous n’avez rien à configurer. Par contre si vous en rajoutez,
il faut les indiquer dans la section simple_urlengine_entrypoints pour les déclarer et dire quels modules et quels
types de requêtes ils concernent. Les paramètres de cette section ont la forme :

nom_du_script_sans_suffix = "liste de sélecteur séparé par un espace"

Les sélecteurs peuvent être de l’une de ces formes :


– mod~act@req : le point d’entrée concerne l’action act du module mod pour le type de requête req
– mod~*@req : le point d’entrée concerne toutes les actions du module mod pour le type de requête req
– @req : le point d’entrée concerne toutes les actions de tous les modules pour le type de requête req
Vous indiquez ainsi quelles actions passent par quel point d’entrée.
Exemple :
[simple_urlengine_entrypoints]
index = "@classic"
xmlrpc = "@xmlrpc"
jsonrpc = "@jsonrpc"
testnews = "unittest~url2@classic unittest~url3@classic"
foo/bar = "unittest~url4@classic"
news = "news~*@classic"

– le point d’entrée index.php concerne toutes les actions des requêtes de type classic (sauf celles spécifiées dans
d’autres points d’entrées. C’est donc le point d’entrée par défaut pour les requêtes de type classic.
– idem pour le point d’entrée xmlrpc.php et jsonrpc.php qui concernent respectivement toutes les actions des re-
quêtes de type xmlrpc et toutes les actions des requêtes de type jsonrpc.
– le point d’entrée testnew.php concerne l’action url2 et url3 du module unittest pour le type de requête classic
– le point d’entrée foo/bar.php concerne l’action url4 du module unittest pour le type de requête classic
– le point d’entrée news.php concerne tout le module news
Pour l’action url2, jUrl génèrera donc l’URL testnews.php ?module=unittest&action=url2&autresparametres..

URL avec https

Avec le moteur d’URL simple, pour indiquer les URLs des actions qui devront être en https, vous indiquez la liste des
actions dans l’option simple_urlengine_https dans la section urlengine. La syntaxe est la même que dans la section
simple_urlengine_entrypoints.
[urlengine]
...
simple_urlengine_https = "unittest~url6@classic @xmlrpc"

[simple_urlengine_entrypoints]
...

18.6 Moteur d’urls significatives

Le moteur d’url "significant" permet d’attribuer à chaque action une url spécifique de la forme que l’on veut.
Le principe de configuration pour ce moteur est d’indiquer dans un fichier var/config/urls.xml toutes les formes
d’URLs possibles de l’application et les actions qui leurs sont associées. Voici un exemple de fichier :
Jelix 1.0.6
Guide du développeur
133 / 225

<urls xmlns="http://jelix.org/ns/urls/1.0">
<classicentrypoint name="index" default="true">

<url pathinfo="/news/:annee/:mois/:id-:title" module="news" action="view">


<param name="annee" type="year"/>
<param name="mois" type="month" />
<param name="id" type="number" />
<param name="title" escape="true" />
</url>

<url pathinfo="/articles/:rubrique/:id_art" module="cms" action="show">


<param name="id_art" regexp="\d+"/>
</url>

</classicentrypoint>
<classicentrypoint name="shop">
<url pathinfo="/:category/:product" module="unittest" action="url2">
<param name="product" regexp="\d{2}" />
<static name="mystatic" value="valeur statique" />
</url>
</classicentrypoint>
<classicentrypoint name="foo/bar">
<url handler="urlsig" module="unittest" action="url4" />
</classicentrypoint>

<classicentrypoint name="news">
<url module="news" />
</classicentrypoint>
<xmlrpcentrypoint name="xmlrpc" default="true" />
<jsonrpcentrypoint name="jsonrpc" default="true" />
</urls>

18.6.1 Balises entrypoint

La balise racine urls contient autant de balises *entrypoint que de points d’entrée disponibles dans votre applica-
tion. Leur nom exact précise le type de requête auxquels ils sont affectés :
– classicentrypoint pour les requêtes classiques
– xmlrpcentrypoint pour du xmlrpc
– etc ...
Chacune de ces balises a un attribut name indiquant le nom du point d’entrée (sans l’extension .php) et éventuelle-
ment un attribut default indiquant si ce point d’entrée est celui par défaut pour le type de requête en question.

18.6.2 Balise url

Chaque point d’entrée définit une ou plusieurs formes d’URLs possibles, sachant que celles qui ne sont pas définies
seront acceptées lors d’une requête sur un point d’entrée spécifié "default".

Spécifier une forme d’URL complète

Selon un pathinfo

Vous voulez indiquer le module et l’action à exécuter pour une forme particulière d’URL. Vous indiquerez alors un
attribut pathinfo, indiquant le "modèle" de la partie pathinfo auquel l’URL doit ressembler, ainsi que le module et
Jelix 1.0.6
Guide du développeur
134 / 225

l’action dans des attributs module et action.


L’attribut pathinfo doit donc contenir la valeur d’un pathinfo. Dans cet exemple, toute URL qui aura pour pathinfo
la valeur "/foo/bar" correspondra au module et action indiqués (module hello, action default :world dans notre cas).
<url pathinfo="/foo/bar" module="hello" action="default:world" />

Selon un pathinfo contenant des parties indéfinies

Il est possible d’indiquer des parties "dynamiques" dans le pathinfo. Elles sont à définir par un deux-points suivi
d’un nom. La valeur trouvée sera alors stockée dans un paramètre du même nom. Dans l’exemple qui suit, le pathinfo
contient deux parties dynamiques : rubrique et id_art.
<url pathinfo="/articles/:rubrique/:id_art" module="cms" action="default:show" ←-
/>

Si on appelle l’URL "/articles/aviation/544", alors les paramètres rubrique et id_art seront crées et auront pour
valeurs respectives "aviation" et "544".
Attention : pour éviter les ressemblances avec d’autres URLs, il faut au moins une partie "statique" (ici "/articles/")
dans l’URL pour la distinguer des autres.

Des parties indéfinies typées ou formatées

Un autre moyen d’éviter ces ressemblances est de spécifier le format ou le type de chaque paramètre. Par défaut le
type est une chaîne classique.
Pour cela il faut indiquer des balises param pour chacun des paramètres dont on veut spécifier le type/format. Elles
devront contenir un attribut name indiquant le paramètre et, soit un attribut type, soit un attribut regexp, contenant
une expression régulière du format (sans délimiteur). Dans notre exemple, nous voulons spécifier que rubrique est
une chaîne et une expression régulière pour id_art :
<url pathinfo="/articles/:rubrique/:id_art" module="cms" action="show">
<param name="rubrique" type="string" />
<param name="id_art" regexp="\d+" />
</url>

Quand le paramètre est de type string il n’est pas obligatoire de mettre une balise param. Les types disponibles sont :

Note : vous devrez bien entendu indiquer les valeurs de ces paramètres lors de l’appel à jUrl.

Des paramètres statiques

Il peut être nécessaire parfois de rajouter des paramètres "statiques", attendues par l’action (celle-ci pouvant être
attribuées à plusieurs URLs différentes), mais non présent dans l’URL. Pour cela il faut ajouter une balise <static>,
avec nom et valeur, comme dans cet exemple :
<url pathinfo="/:category/:product" module="shop" action="product:view">
<param name="product" regexp="\d{2}" />
<static name="details" value="0" />
</url>
Jelix 1.0.6
Guide du développeur
135 / 225

<url pathinfo="/:category/:product/details" module="shop" action="product:view" ←-


>
<param name="product" regexp="\d{2}" />
<static name="details" value="1" />
</url>

Ici on utilise la même action pour deux URLs différentes. Son traitement différera en partie selon le paramètre d-
etails, qu’il ne faut donc pas oublier de donner à jUrl : :get. Dans un cas on afficherait le produit d’un catalogue
avec ses caractéristiques générales, et dans l’autre avec ses caractéristiques générales et détaillées. Cela évite donc de
créer deux actions différentes pour si peu de différence.
On peut aussi utiliser ce mécanisme pour supporter plusieurs langues :
<url pathinfo="/articles/en/:page" module="cms" action="page:view">
<param name="page"/>
<static name="lang" value="en_EN" />
</url>
<url pathinfo="/articles/fr/:page" module="cms" action="page:view">
<param name="page"/>
<static name="lang" value="fr_FR" />
</url>

Là encore, il ne faut pas oublier de donner le paramètre lang à jUrl pour que ce dernier puisse savoir quelle url il doit
renvoyer.

18.6.3 Utiliser un handler spécifique

Nous avons vu précédemment comment utiliser, en fin de compte, un système par défaut d’analyse et de génération
d’URL avec ses pathinfos et paramètres. Il se peut que ce système ne soit pas suffisant. Imaginons par exemple que
vous vouliez transformer une partie de l’information contenu dans le pathinfo, comme par exemple chercher dans une
base de données un id correspondant à un titre contenu dans le pathinfo, et fournir ainsi aux actions, non pas un titre,
mais un id (qui n’est pas contenu dans cette URL).
Ou encore que la partie pathinfo puisse être variable.
Aussi c’est à vous de développer l’analyse de l’URL et d’indiquer l’action à exécuter. Vous le ferez dans une classe
spécialisée :

class myHandlerUrlsHandler implements jIUrlSignificantHandler {

function parse($url){

if(preg_match("/^\/(.*)$/",$url->pathInfo,$match)){
$urlact = new jUrlAction($url->params);
$urlact->setParam(’page’,jUrl::unescape($match[1]));
return $urlact;
}else
return false;
}

function create($urlact, $url){

$p=jUrl::escape($url->getParam(’page’));

$url->pathInfo = "/$f";
Jelix 1.0.6
Guide du développeur
136 / 225

$url->delParam(’page’);
}
}

Le nom de la classe doit commencer par un préfixe que vous voulez et se terminer par UrlsHandler. La classe
sera stockée dans le répertoire classes du module indiqué dans la balise url, sous le nom prefixe.urlhandler.php.
Pour notre exemple :

myhandler.urlhandler.php.

La méthode parse est chargée d’analyser une URL (objet jUrl que vous recevez en paramètre), en l’occurence, l’URL
demandée dans l’application. Si votre handler reconnaît l’URL, parse() doit renvoyer un objet jUrlAction qui contient
toutes les données pour l’action. Sinon il doit renvoyer false.
La méthode create() est appelée à chaque fois que l’application demande la création d’une URL à partir de paramètres
d’action. Elle reçoit donc un objet de type jUrlAction, et un objet de type jUrl. $urlaction contient donc les paramètres
de l’action. Ces paramètres ont déjà été inclus dans l’objet $url. Vous devez donc modifier $url de façon à produire
l’URL correspondante à l’action demandée. Dans l’exemple, on récupère le paramètre page, que l’on incorpore dans
le pathinfo. Et comme il est dans le pathinfo, on le supprime alors des paramètres.
Notez l’usage de jUrl : :escape() et jUrl : :unescape(), pour "nettoyer" les chaînes à inclure dans un pathinfo (accents
enlevés par ex).
Enfin dans le fichier urls.xml, vous devez indiquer l’utilisation de ce handler :
<classicentrypoint name="wiki">
<url handler="myHandler" module="unittest" action="url4" />
</classicentrypoint>

Depuis jelix 1.0 beta1, vous pouvez indiquer un handler d’un autre module. Exemple :
<classicentrypoint name="wiki">
<url handler="autremodule~myHandler" module="unittest" action="url4" />
</classicentrypoint>

18.6.4 Une même URL pour plusieurs actions possibles

Imaginons que nous avons une URL de ce type : "/article/54-titre" et par défaut, cela affiche l’article 54 avec une
action nommée view par exemple :
<url pathinfo="/article/:id_art-:title" module="cms" action="view" />

On veut pouvoir, sans changer l’url, indiquer d’autres actions dans certains cas, avec un paramètre action :
– "/article/54-titre ?action=edit"
– "/article/54-titre ?action=delete"
Note : On pourrait faire aussi /article/54-titre/edit ou /article/54-titre/delete , avec donc plusieurs balises urls, ce qui
nous éviterait ce qui suit. Mais ce n’est pas très pratique quand l’URL est appelée suite à un formulaire par exemple.
Pour indiquer les actions alternatives autorisées, on ajoute un attribut actionoverride, contenant la liste des actions
séparées par un espace ou une virgule :
<url pathinfo="/article/:id_art-:title" module="cms" action="view" ←-
actionoverride="edit,delete" />
Jelix 1.0.6
Guide du développeur
137 / 225

18.6.5 Indiquer qu’un point d’entrée est dédié à un module particulier

Vous n’avez pas forcément envie d’indiquer une URL significative pour les actions d’un module particulier. Par
contre vous avez créé un point d’entrée dédié à un module. Toutes ces actions passeront par ce point d’entrée. Vous
avez juste alors à faire comme ceci :
<classicentrypoint name="news">
<url module="news" />
</classicentrypoint>

18.6.6 Spécifier des URLs en https à certaines actions

Pour certaines actions vous voulez que l’accès soit en mode sécurisé de http (SSL). Vous indiquez alors un attribut
https sur les balises <url> en question avec la valeur true. Si cela concerne toutes les actions/URLs d’un point
d’entrée, alors vous mettrez cet attribut sur la balise <*entrypoint> correspondante.
Attention : pour le moment, Jelix ne vérifie pas lors de l’exécution d’une action que la requête a été faite en https ou
non.

18.6.7 Mod_rewrite et suppression du nom du point d’entrée dans l’URL

Vous préférez peut être que l’analyse des URLs se fasse par le serveur web, grâce au module rewrite pour apache par
exemple. Vous allez donc écrire les règles de réécriture.

Réécriture complète par le serveur web

On appelle ici réécriture complète, la réécriture qui consiste à fournir à Jelix des URLs simples (index.php ?module=...&actio
à partir d’URLs significatives.
Pour cela, vous devez indiquer à Jelix, dans la configuration, de ne pas analyser les URLs :
[urlengine]
..
enableParser = off

Vous devez bien sûr remplir un fichier urls.xml de façon à ce que Jelix génère dans vos templates et ailleurs, les
URLs attendues par vos règles de rewrite.
Et bien sûr, vous devez ensuite mettre dans un fichier .htaccess les règles de réécritures.
Si vous voulez définir des URLs qui ne contiennent pas le nom du point d’entrée, vous devez alors indiquer sur les
balises <url> l’attribut noentrypoint="true" (ou sur la balise <*entrypoint> si toutes les URLs de ce point d’entrée
sont conçernées). Ainsi Jelix n’ajoutera pas le nom du point d’entrée (index.php) dans l’URL.

Suppression du nom du point d’entrée dans l’URL

Un exemple d’utilisation du mod_rewrite n’est pas forcément de transformer complètement les URLs, mais par
exemple d’ajouter le fichier index.php dans les URLs dans lesquelles on l’aurait supprimé pour faire "joli".
Par exemple nos URLs sont de la forme :
http://monsite.com/index.php/news/2007-02-08-il-neige-a-lille.html

Et on souhaite qu’elles deviennent :


Jelix 1.0.6
Guide du développeur
138 / 225

http://monsite.com/news/2007-02-08-il-neige-a-lille.html

Voyons comment faire.


Tout d’abord, il faut bien sûr utiliser le moteur d’URL "significant" et définir un fichier urls.xml. Comme pour la
réécriture complète vous devez indiquer sur les balises <url> ou <*entrypoint> l’attribut noentrypoint="true".
Ainsi Jelix n’ajoutera pas le nom du point d’entrée (index.php) dans les URLs concernées.
Ensuite on va utiliser le rewriteEngine de Apache d’une façon toute simple : le chemin appelé sera rajouté après
index.php. En clair il faut copiez ceci dans un fichier .htaccess dans le dossier www de votre application (ou dans la
section virtualhost de la configuration apache) :
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
</IfModule>

Observez bien :
– 3ème et 4ème ligne : Réécrire l’URL seulement si la requête ne correspond pas à un fichier déjà existant, ou un
dossier déjà existant. Ainsi on préserve ses dossiers d’image, de feuille de style, etc. de la règle de réécriture.
– 5ème ligne : Tout prendre, et mettre après index.php/
On retrouve ainsi notre point d’entrée index.php ainsi que notre pathinfo.
Il se peut que sur certaines configurations, vous ayez une erreur apache du type "Error : No input file specified", en
particulier quand PHP est exécuté en CGI avec cgi.fix_pathinfo=0 dans php.ini.
Depuis Jelix 1.0.2, il y a une solution. Il faut changer la dernière rêgle en :
RewriteRule ^(.*)$ index.php?jpathinfo=/$1 [L,QSA]

Ainsi le but est de mettre le pathinfo dans un paramétre de la requête. Pour que cela fonctionne pleinement, il faut
ajouter dans la configuration de Jelix, dans la section urlengine, le paramètre pathInfoInQueryParameter qui doit
contenir le nom du paramètre (ici dans l’exemple jpathinfo)
[urlengine]
...
pathInfoInQueryParameter = jpathinfo
Jelix 1.0.6
Guide du développeur
139 / 225

Chapitre 19

jAuth : système d’authentification

Le système d’authentification de Jelix ne s’occupe que d’une seule chose : gérer des logins/mots de passe et des
utilisateurs. Il repose sur des drivers pour accéder aux données d’un utilisateur. C’est ainsi qu’il peut s’appuyer sur
une base de données, un annuaire LDAP etc. Pour le moment, il existe un driver pour une base de donnée, un driver
pour un annuaire géré par un serveur LDS, et un driver pouvant utiliser une classe quelconque.

19.1 Mise en oeuvre

Le système d’authentification repose sur plusieurs choses :


– un plugin pour le coordinateur, nommé auth et livré en standard avec jelix, vérifiant si l’authentification est effec-
tuée pour les actions où elle est nécessaire
– une classe jAuth, permettant d’effectuer les différentes opérations sur l’authentification et la gestion des logins.
Cette classe repose sur un système de driver.
– un module, jauth, proposant un contrôleur et des templates par défaut. Il n’est en principe pas indispensable, vous
pouvez tout à fait utiliser votre propre contrôleur, la mise en oeuvre étant relativement simple.
– un objet stocké en session, contenant les informations sur l’utilisateur. Il est fourni par le driver. Cela peut être un
objet DAO, une simple classe etc.

19.1.1 Installer le plugin auth pour le coordinateur

Le rôle du plugin auth :


– Vérifier l’authentification
– Gérer un timeout de session (optionnel)
– Gérer la persistance de l’authentification via un cookie (optionnel)
– Indiquer le driver à utiliser pour jAuth
– Indiquer les paramètres pour le driver (DAO pour jAuthDb, cn/sn/uid pour un driver LDAP etc...)
– Indiquer ce qu’il faut faire en cas de non authentification
Aussi, dés lors que l’on veut utiliser le système d’authentification, il faut activer le plugin et le configurer, il est
indispensable.
Dans le fichier de configuration, vous indiquerez alors dans la section plugins :
[plugins]
auth = "auth.coord.ini.php"

le fichier de configuration auth.coord.ini.php du plugin est une copie du fichier /lib/jelix/plugins/coord/auth/auth.coord.ini.ph


que vous placez dans le repertoire var/config/ de votre application
Jelix 1.0.6
Guide du développeur
140 / 225

Note : pour jelix 1.0beta2 et précédent, le ficher auth.plugin.ini.php.dist se trouve dans un autre répertoire, lib/jelix-
plugins/auth/auth.plugin.ini.php.dist. De plus, il faut vérifier que le paramètre pluginsPath dans la configuration
contient bien lib :jelix-plugins. (ce n’est pas nécessaire dans jelix 1.0 beta3 et suivant, car le plugin se trouve dans
lib/jelix/plugins/, qui est déclaré automatiquement).
Note sur la déclaration du plugin : Si vous utilisez plusieurs plugins de coordinateur, l’ordre de déclaration des
plugins dans le fichier de configuration a une importance. Ainsi si vous placez le plugin auth en premier, il faut savoir
que les autres plugins ne seront pas éxécutés dans le cas où le plugin auth demande une redirection (par exemple la
page de login). En général, il convient donc de placer ce plugin après les plugins ne nécessitant pas d’authentification.
Pour en savoir plus sur les plugins : plugins

19.1.2 Configurer le plugin

Vous devez ensuite éditer le fichier auth.coord.ini.php, pour indiquer la configuration du système d’authentification.
Voici les différents paramètres.

Indiquer le driver

Vous devez indiquer le nom du driver utilisé au niveau de l’option driver. Vous devez ensuite avoir une section
portant ce même nom, pour les options propres au driver.
driver=XXX

[XXX]
foo=bar

Par exemple, pour le driver Db (les informations sont stockées alors dans une base de donnée) :
driver=Db

[Db]
dao = "mon_dao"
password_crypt_function = md5

Pour en savoir plus sur les spécificités de chaque driver disponibles, ou même en créer un, consultez la documentation
sur les drivers jauth.

Timeout

L’option timeout permet d’indiquer en minutes le temps d’inactivité au bout duquel l’authentification ne sera plus
valide. Si vous mettez 0, il n’y a pas de limite de temps. La session expirera à la fermeture du navigateur.

Contrôler l’authentification pour chaque action

Le plugin peut contrôler si l’action demandée a besoin d’une authentification ou non. Avec l’option auth_required
dans le fichier ini, vous pouvez dire si par défaut toutes les actions nécessitent une authentification (valeur "on"), ou
si par défaut, il n’y en a pas besoin (valeur "off").
auth_required=on

Dans un cas comme dans l’autre, il faut pouvoir gérer les exceptions (par exemple, une action qui ne nécessite pas
une authentification alors que par défaut toutes les actions le nécessitent). Les exceptions sont indiquées au niveau des
contrôleurs, dans les paramètres de plugin.
Jelix 1.0.6
Guide du développeur
141 / 225

class xxxCtrl extends jController {

public $pluginParams = array( ... );

Pour les actions concernées, vous indiquerez le parametre auth.required et le mettrez à false ou true. Par exemple
pour les actions index et affiche, il faut une authentification, alors que pour le reste des actions du contrôleur ("*"
indique "toutes les actions"), ce n’est pas utile :
class xxxCtrl extends jController {

public $pluginParams = array(


’*’=>array(’auth.required’=>false),
’index’=>array(’auth.required’=>true),
’affiche’=>array(’auth.required’=>true),
);
}

Voir la page sur les plugins de coordinateurs pour mieux comprendre l’usage de $pluginParams.

Spécifier le comportement en cas de défaut d’authentification

Si l’authentification n’est pas faite alors que l’action en nécessite une, le plugin va alors agir en fonction de l’option
on_error.
Si vous mettez la valeur 1, alors le plugin génèrera une erreur dont le message (ou plutôt la clé de la locale du
message) est dans l’option error_message.
Si par contre la valeur est 2, alors le plugin exécutera l’action définie dans l’option on_error_action. Cela peut
être une action d’un contrôleur du module auth (comme c’est le cas par défaut), ou alors une action de votre propre
contrôleur dans un module tierce. Cette action en général affiche une page demandant un login/mot de passe (mais
cela peut être autre chose...)

Persistance de l’authentification

jAuth propose un mécanisme de persistance d’authentification. C’est à dire la reconnaissance automatique de l’utili-
sateur quand il revient sur le site, même plusieurs jours après sa dernière visite (et donc après avoir perdu sa session
PHP...). Cela se fait par le biais d’un cookie dans lequel sont stockés un certain nombre d’information dont une partie
encrypté.
Vous avez pour cela deux paramètres important :
– persistant_enable : mettez le à on pour activer la persistance de l’authentification
– persistant_crypt_key : c’est un paramètre à renseigner obligatoirement. Vous devez remplacer la valeur par dé-
faut ! Ce paramètre doit contenir une chaîne quelconque de votre choix (plus de 10 lettres de préférence). Elle
servira de clé d’encryptage pour les données stockées dans le cookie. Si vous changez de clé en cours de route, les
cookies seront invalides et les utilisateurs ne sont pas reconnus. Ils devront s’authentifier à nouveau.
D’autres paramètres sont disponibles :
– persistant_cookie_name : indique le nom du cookie à utiliser. Par défaut : "jelixAuthentificationCookie".
– persistant_duration : indique la durée en jour de la validité du cookie. Par défaut c’est une journée.
– persistant_cookie_path : le chemin du cookie. Par défaut (vide), il vaut la valeur de basePath dans la config
générale.
Jelix 1.0.6
Guide du développeur
142 / 225

19.2 Utiliser le contrôleur par défaut

Le module jauth propose des contrôleurs que vous pouvez utiliser pour gérer les actions de connexion, de décon-
nexion, en faisant appel à la classe jAuth. Il propose aussi des zones et des templates.
À l’avenir, il proposera également des zones de formulaire de changement de mot de passe, de formulaire de des-
truction de compte (si un utilisateur veut supprimer un compte sur une appli type portail), de création de compte et de
récupération de mot de passe. Bien sûr, on aurait des paramètres de configuration qui permettrait de dire si on autorise
un utilisateur à supprimer son compte, à récupérer son mot de passe, etc...

19.2.1 Configuration classique

Quand on utilise le module jauth, il est possible d’ajouter des options de configuration propre au module. Par
exemple, une configuration possible dans le fichier auth.plugin.ini.php peut être celle-ci :
driver = Db
on_error_action = "jauth~login:out"
after_login = "myapp~default:index"
after_logout = "jauth~login:form"
on_error_sleep = 3
[Db]
dao = "jauth~jelixuser"

Le paramètre on_error_sleep est le nombre de secondes d’attente quand l’utilisateur a donné un mauvais mot de
passe ou login. Pour after_login et after_logout, voir plus bas.
Vous remarquerez aussi que dans l’exemple, on utilise le driver Db. Le module jauth propose en effet un DAO pour
le driver Db. Si vous l’utilisez, il faut créer alors la table jlx_user suivante (ici pour mysql) :
CREATE TABLE ‘jlx_user‘ (
‘usr_login‘ VARCHAR( 50 ) NOT NULL ,
‘usr_email‘ VARCHAR( 255 ) NOT NULL ,
‘usr_password‘ VARCHAR( 50 ) NOT NULL ,
PRIMARY KEY ( ‘usr_login‘ )
);

Vous pouvez bien sûr ajouter d’autres champs, il faudra alors proposer votre propre DAO. (voir la doc sur le driver
Db).
A noter que vous pouvez surcharger les templates du module en créant vos propres templates dans le dossier

myapp/
var/
themes/
default/
jauth/

19.2.2 Configuration de la redirection

Dans la configuration du plugin, vous devez spécifier les paramètres after_login, after_logout, et éventuellement les
options enable_after_login_override et enable_after_logout_override
Les paramètres after_login et after_logout doivent contenir les selecteurs des actions vers lesquelles il faut rediriger
une fois que l’identification ou la déconnexion sont effectuées. Ils sont obligatoires. Si vous ne les indiquez pas, vous
allez avoir des redirections vers l’action jauth~default :index qui n’existe pas, donc une erreur...
Jelix 1.0.6
Guide du développeur
143 / 225

Il est possible dans un formulaire d’authentification ou de déconnexion, d’ajouter un paramètre caché contenant
l’URL vers laquelle il faut rediriger. Cela permet de rediriger vers une page différente en fonction de la page sur la-
quelle on est quand on se connecte ou déconnecte. Dans ce cas, ce paramètre caché doit se nommer "auth_url_return",
et doit contenir l’URL. Et vous devez mettre les paramètres de configuration enable_after_login_override et/ou en-
able_after_logout_override à "on".

19.3 Utiliser son propre contrôleur

Vous pouvez utiliser vos propres contrôleurs pour gérer l’authentification : formulaire de login, connexion, décon-
nexion. Vous ferez appel alors à la classe jAuth et ses méthodes statiques pour verifier les logins/mots de passe,
connecter et déconnecter un utilisateur.

19.4 classe jAuth

C’est la classe principale du système d’authentification. Toutes ses méthodes sont statiques. Elle permet de gérer un
utilisateur, de "connecter"/"déconnecter" un utilisateur etc.. Vous appellerez ces méthodes quand bon vous semble,
sachant que les contrôleurs du module jauth peuvent se charger pour vous d’une bonne partie du travail. Voir son
descriptif dans la référence.
l’objet user que vous passez à certaines méthodes vous est donné par jAuth lui même. C’est un objet contenant les
données d’un utilisateur et il n’a pas de classe précise : son type dépend du driver utilisé et éventuellement de sa
configuration (pour le driver Db, on peut fournir un DAO de notre choix par exemple). Il doit par contre respecter
l’interface attendue par le driver, et doit avoir au moins un champ login et un champ password.
jAuth n’a pas à être surchargée. Elle s’appuie sur des "drivers" pour gérer les différents types d’authentification.

19.4.1 Évènements

Pour la plupart des méthodes de jAuth, un évènement est émis. Cela permet à des modules tiers d’être au courant des
différentes actions d’authentification, et donc de charger des données supplémentaires dans l’objet user, ou de gérer
les données dépendantes à l’utilisateur etc.
– AuthNewUser : indique qu’un utilisateur vient d’être ajouté
– AuthCanRemoveUser : demande si on peut supprimer l’utilisateur ou pas
– AuthRemoveUser : l’utilisateur a été supprimé
– AuthUpdateUser : l’utilisateur vient d’être mis à jour
– AuthCanLogin : demande si l’utilisateur peut se connecter
– AuthLogin : un utilisateur vient de se connecter
– AuthLogout : un utilisateur vient de se déconnecter

19.5 Les drivers pour jAuth

Il existe en standard plusieurs drivers pour l’authentification dans Jelix.

19.5.1 Db

Le driver Db propose une authentification pour laquelle les informations sont stockées en base de donnée. Pour cela,
ce driver Db se repose sur un dao, qu’il faut indiquer dans le fichier de configuration d’authentification :
Jelix 1.0.6
Guide du développeur
144 / 225

driver= Db

[Db]
dao = "monmodule~mondao"
password_crypt_function = "md5"

Ce que vous indiquez au niveau du paramètre dao, c’est un sélecteur vers le fichier dao que vous voulez utiliser. Vous
pouvez utiliser celui fourni dans le module jauth :
dao = "jauth~jelixuser"

Le paramètre password_crypt_function indique la fonction à utiliser pour crypter les mots de passe. Vous pouvez
fournir votre propre fonction de cryptage (en la définissant dans le fichier application.init.php par exemple) et indiquer
son nom ici.
Pour le dao que vous indiquez, il doit avoir au moins les propriétés "login" et "password". Vous pouvez rajouter
d’autres propriétés, autant que vous voulez. Il doit aussi y avoir au moins les méthodes qu’il y a dans le dao jelixuser
du module jauth :
– getByLoginPassword (login, password)
– getByLogin(login)
– updatePassword(login,password)
– deleteByLogin(login)
– findByLogin(pattern)
Note : la table sur laquelle repose le dao, doit avoir comme clé primaire le champs du login.

Exemple

Imaginons que l’on ait la table suivante (script mysql) :


CREATE TABLE ‘jlx_user‘ (
‘usr_login‘ varchar(50) NOT NULL default ’’,
‘usr_password‘ varchar(50) NOT NULL default ’’,
‘usr_email‘ varchar(255) NOT NULL default ’’,
PRIMARY KEY (‘usr_login‘)
) AUTO_INCREMENT=2 ;

On a bien le login comme étant la clé primaire, et au moins le champs password.


On crée ensuite le dao suivant, comme indiqué plus haut :
<?xml version="1.0" encoding="UTF-8"?>
<dao xmlns="http://jelix.org/ns/dao/1.0">
<datasources>
<primarytable name="usr" realname="jlx_user" primarykey="usr_login" />
</datasources>
<record>
<property name="login" fieldname="usr_login"
required="yes" datatype="string" maxlength="50" />

<property name="email" fieldname="usr_email"


datatype="string" required="yes" maxlength="255" />

<property name="password" fieldname="usr_password" datatype="string"


maxlength="50" selectmotif="%s" updatemotif="" insertmotif="%s" />
</record>
Jelix 1.0.6
Guide du développeur
145 / 225

<factory>
<method name="getByLoginPassword" type="selectfirst">
<parameter name="login" />
<parameter name="password" />

<conditions>
<eq property="login" expr="$login" />
<eq property="password" expr="$password" />
</conditions>
</method>

<method name="getByLogin" type="selectfirst">


<parameter name="login" />

<conditions>
<eq property="login" expr="$login" />
</conditions>
</method>

<method name="updatePassword" type="update">


<parameter name="login" />
<parameter name="password" />

<values>
<value property="password" expr="$password"/>
</values>
<conditions>
<eq property="login" expr="$login" />
</conditions>
</method>

<method name="deleteByLogin" type="delete">


<parameter name="login" />
<conditions>
<eq property="login" expr="$login" />
</conditions>
</method>

<method name="findByLogin" type="select">


<parameter name="pattern" />
<conditions>
<like property="login" expr="$pattern" />
</conditions>
<order>
<orderitem property="login" way="asc" />
</order>
</method>
<method name="findAll" type="select">
<order>
<orderitem property="login" way="asc" />
</order>
</method>
</factory>
</dao>

Et dans le fichier auth.plugin.ini.php, on indique ce dao que l’on aura stocké dans le module foo sous le nom
user.dao.xml.
Jelix 1.0.6
Guide du développeur
146 / 225

driver= Db

[Db]
dao = "foo~user"
password_crypt_function = "md5"

19.5.2 Class

C’est un driver plus universel que celui de Db, dans la mesure où vous devez lui fournir une classe, dans laquelle
vous faîtes ce que vous voulez. Elle doit respecter l’interface jIAuthDriverClass. Cette classe doit être stockée dans le
répertoire "classes" d’un de vos modules, comme n’importe quelle classe métier.
Dans la configuration du plugin jauth, vous devez mettre :

driver= Class

[Class]
class = "monmodule~maclass"
password_crypt_function = "md5"

19.5.3 LDS

C’est un driver qui repose sur un serveur LDS (http ://lds.linbox.org/). Il appelle l’API xml-rpc d’un serveur LDS.
La configuration que vous devez indiquer doit donc être celle-ci :

driver= LDS

[LDS]
host=foo.com
port=80
login= foo
password= bar
scheme= https

Le driver interrogera donc le serveur foo.com sur le port 80, avec le login foo et le mot de passe bar, via une
connexion sécurisée https.

19.5.4 Créer un driver

Vous avez peut-être votre propre système d’authentification, que vous voulez mieux intégrer dans le framework.
Dans ce cas, il vous faut créer un driver. Au passage, nous acceptons toutes contributions de ce type !
Pour les détails, voir la page sur la création des drivers d’authentification.
Jelix 1.0.6
Guide du développeur
147 / 225

Chapitre 20

jAcl : système de droits

Jelix propose un système de gestion de droits, jAcl, comportant des possibilités similaires à ce qui peut exister
ailleurs.
jAcl est basé sur un système de driver. Le driver fourni par défaut est un driver "db" (noté dans la documentation
"jAcl.db"), dont la gestion des droits repose sur une base de données et qui tente de répondre à des problématiques
courantes de gestion de droits.
Notez que l’utilisation de jAcl n’est pas obligatoire pour faire fonctionner une application Jelix. À moins que les
modules utilisés fassent appel à jAcl bien entendu.
– *Note** : la version 1.1 de Jelix contiendra jAcl2, qui est plus simple d’utilisation que jAcl. Cependant jAcl
restera disponible dans Jelix 1.1.

20.1 Les concepts généraux de jAcl

jAcl propose un système qui répond à la plupart des besoins en matière de gestion de droits. Il comporte divers
éléments qui ensemble définissent des droits.

20.1.1 Éléments composant un droit

Il faut distinguer les différents éléments qui entrent en jeu dans le système de droits :
– un sujet
– une valeur de droit
– un utilisateur
– une ressource (facultatif)
une combinaison de chacun de ces types d’éléments représente un droit.

Sujet

C’est un intitulé représentant un type de ressource ou une fonctionnalité sur laquelle on veut apposer un droit. Par
exemple, "cms.articles" pourrait être le sujet regroupant les droits sur la gestion des articles d’un CMS.
Par convention, afin d’éviter les collisions entre différents modules, le nom du sujet devrait commencer par le nom
du module. Mais ce n’est pas une obligation.
Jelix 1.0.6
Guide du développeur
148 / 225

Valeur de droit

C’est une chaîne, une valeur indiquant précisément un droit. Pour un sujet donné, il y a un ensemble de valeurs
précises possibles. Par exemple, pour le sujet "cms.articles", on pourrait avoir les valeurs "LIRE", "MODIFIER",
"CREER", "PUBLIER", "EFFACER". Et pour le sujet "comments.management", juste les valeurs "EFFACER" et
"MODIFIER".
Ainsi donc, les valeurs de droits sont regroupées en groupes de valeurs.
À noter que les intitulés des valeurs de droits dépendent totalement de la manière dont sont stockées les droits dans
le système accédé par le driver.

Utilisateur

Un droit s’exerce toujours sur un ou plusieurs utilisateurs. Mais cette notion est transparente du point de vue de
l’API de la classe jAcl. C’est le driver qui s’occupe de "reconnaître" l’utilisateur en cours (au moyen de jAuth en
principe). Il se peut même que le driver repose sur un système où les utilisateurs sont dans des groupes auxquels les
droits s’appliquent (comme c’est le cas de jAcl.db). Mais vous n’avez pas à vous en préoccuper lors de l’utilisation
de jAcl.

Ressource

Dans la plupart des cas, l’association sujet + utilisateur + valeur de droit suffit. Mais parfois on veut pouvoir avoir
une granularité plus fine.
Par exemple, dans un système CMS, on veut pouvoir donner le droit de modification à un utilisateur sur ses propres
articles, mais pas sur ceux des autres. Il faut alors rajouter dans cette association l’identifiant de l’article.
Par exemple, on donnera les valeurs de droits suivants
– "CREER" sur le sujet "cms.articles" pour le groupe "redacteurs"
– "MODIFIER" sur la ressource "monarticle" pour l’utilisateur toto faisant parti du groupe "redacteurs".

20.1.2 Principes de fonctionnement

Le cœur de jAcl contient donc des relations entre trois ou quatre types d’élements.
La mémorisation d’une relation entre un sujet, un utilisateur et une valeur (plus éventuellement une ressource), définit
un droit. Quand une relation n’existe pas entre un sujet donné, un utilisateur donné et une valeur donnée, alors cela
signifie qu’il n’y a pas de droit défini sur ce triplet.
Par exemple, si on définit juste ces droits suivants dans le système :
– "LIRE" sur le sujet "cms.articles" pour l’utilisateur "laurent"
– "CREER" sur le sujet "cms.articles" pour l’utilisateur "laurent"
– "MODIFIER" sur le sujet "cms.articles" pour l’utilisateur "laurent"
L’utilisateur laurent aura donc les droits LIRE, CREER et MODIFIER sur le sujet cms.articles, mais pas le droit
EFFACER puisque la relation n’existe pas.
Un module CMS qui repose sur ces droits devra, pour savoir ce que peut faire un utilisateur, interroger jAcl, en lui
demandant si par exemple l’utilisateur courant a le droit MODIFIER au sujet de "cms.articles". Si oui, alors le module
pourra afficher un bouton "modifier" dans l’interface d’administration, et ne l’affichera pas sinon. (Le module devra
également faire cette vérification lors de la sauvegarde d’un article, pour éviter les "fraudes" ;-) ).
Jelix 1.0.6
Guide du développeur
149 / 225

20.2 Utiliser jAcl dans ses modules

Quand vous voulez que votre module fonctionne selon des droits, il vous faut durant la réalisation de ce module :
1. déterminer des sujets et des valeurs de droits que vous utiliserez
2. éventuellement les enregistrer dans le système de droits utilisé par le driver que vous indiquez à jAcl : dans
un annuaire ldap si vous utilisez un driver ldap (non fourni pour le moment) ou une base de données si vous
utilisez par exemple le driver jAcl.db.
Ensuite vous pouvez utiliser les méthodes statiques de jAcl pour savoir si l’utilisateur courant a tel droit sur tel ou tel
sujet.
Si le driver gère des groupes d’utilisateurs, vous n’avez pas à les indiquer lors de ces interrogations : le driver s’en
occupe automatiquement. Notez qu’un driver pour jAcl peut utiliser jAuth pour l’authentification.

20.2.1 Configuration

Avant toute chose vous devez indiquer quel driver vous utilisez pour jAcl. Les drivers sont des plugins stockés dans
un répertoire acl d’un dépôt de plugins. Un plugin pour jAcl est une classe fooAclDriver (foo étant le nom du plugin)
qui doit implémenter l’interface jIAclDriver et qui est enregistrée dans un fichier foo.acl.php. Par exemple le driver
"db" est stocké dans db/db.acl.php et est défini dans la classe dbAclDriver.
Dans la configuration de l’application, vous devriez avoir une section acl :
[acl]
driver=db

Au niveau de l’option driver vous devez y mettre le nom du driver utilisé.

20.2.2 Interrogation du système de droit

Vous avez principalement deux méthodes statiques de jAcl à connaître : check et getRight.

jAcl : :getRight

jAcl : :getRight() permet de savoir toutes les valeurs possibles à propos d’un sujet, pour lesquelles un droit à été
défini sur l’utilisateur.
$list = jAcl::getRight("cms.articles");

En reprenant l’exemple de l’article jAcl.db, si l’utilisateur fait parti du groupe "lecteurs", la liste vaudra :
array(’LIST’,’READ’);

si il appartient au groupe des redacteurs :


array(’LIST’,’READ’, ’CREATE’,’UPDATE’,’DELETE’);

Si vous indiquez en plus une ressource, par exemple "opinions" comme dans notre exemple :
$list = jAcl::getRight("cms.articles", "opinions");

si l’utilisateur fait parti du groupe "lecteurs", la liste vaudra alors :


array(’LIST’,’READ’, ’UPDATE’);

si il appartient au groupe des rédacteurs, cela ne change pas, puisque les rédacteurs ont de toute façon le droit de
modifier tout les articles, comme cela a été défini précédemment :
array(’LIST’,’READ’, ’CREATE’,’UPDATE’,’DELETE’);
Jelix 1.0.6
Guide du développeur
150 / 225

jAcl : :check

C’est probablement la méthode que vous utiliserez le plus avec jAcl. Elle permet de savoir si l’utilisateur a tel ou tel
droit, et renvoi donc true ou false. Exemple :
if( jAcl::check("cms.articles","CREATE")){
// code à executer si l’utilisateur a le droit de créer un article

}else{
// code à executer si l’utilisateur n’a pas le droit de créer un article
}

Pour interroger sur une ressource précise :


$article_id = "opinions";

if( jAcl::check("cms.articles","UPDATE", $article_id)){


// code à executer si l’utilisateur a le droit de modifier l’article indiqué

}else{
// code à executer si l’utilisateur n’a pas le droit de modifier l’article ←-
indiqué
}

Vérification automatique

Dans les contrôleurs dont on veut vérifier les droits automatiquement, on peut utiliser le plugin jacl pour le coordi-
nateur.
Pour ce faire, activez le plugin jacl dans la configuration de l’application
[plugins]
jacl = jacl.coord.ini.php

Copiez le fichier lib/jelix/plugins/coord/jacl/jacl.coord.ini.php.dist dans var/config/index/jacl.coord.ini.php


Éditez ce fichier pour indiquer les actions vers lesquelles aller en cas de défaut de droits, ou le message à afficher.
Et dans vos contrôleurs, mettez les valeurs suivantes dans la propriété $pluginParams :

public $pluginParams = array(


’jacl.right’=>array(’sujet’, ’valeur’)
...
);

Ou alors, pour vérifier une série de droits que l’utilisateur doit posséder :

public $pluginParams = array(


’jacl.rights.and’=>array(
array(’sujet’, ’valeur’),
array(’sujet’, ’valeur’),
...
),
...
);

ou encore, pour vérifier que l’utilisateur possède un des droits parmis une liste :
Jelix 1.0.6
Guide du développeur
151 / 225

public $pluginParams = array(


’jacl.rights.or’=>array(
array(’sujet’, ’valeur’),
array(’sujet’, ’valeur’),
...
),
...
);

Plugins de template ifacl et ifnotacl

Des plugins de templates sont disponibles pour générer des portions de contenus en fonction des droits. Leurs argu-
ments sont exactement les mêmes que jAcl : :check.
{ifacl "cms.articles","CREATE"}
<input type="button" value="Créer un article" />
{else}
<p>Vous ne pouvez pas créer d’articles.</p>
{/ifnotacl}

Il y aussi {ifnotacl} qui est le contraire de ifacl, c’est à dire qui test si l’utilisateur n’a pas le droit indiqué.
La même chose avec une ressource :
{ifacl "cms.articles","UPDATE", $article_id}
<input type="button" value="Modifier l’article" />
{/ifacl}

20.3 Les concepts de jAcl.db

jAcl.db est le driver "db" pour jAcl et se sert d’une base de données pour stocker les droits. Il implémente les concepts
généraux de jAcl, avec en plus une gestion de groupes d’utilisateurs. Aussi les éléments qui entrent en jeu dans le
système de droit de jAcl.db sont :
– un sujet
– une valeur de droit
– un groupe d’utilisateurs
– une ressource (facultatif)
une combinaison de chacun de ces types d’éléments représente un droit.

20.3.1 Groupes et Utilisateur

Chaque utilisateur appartient à un ou plusieurs groupes. Un droit s’exerce toujours sur un ou plusieurs groupes et
non pas sur un utilisateur précis.
Il est possible d’affecter des droits à un seul utilisateur, mais cela se traduit en fait par l’existence d’un groupe ’privé’
propre à chaque utilisateur (afin de faciliter les traitements). En clair, chaque utilisateur possède son groupe personnel
dans lequel il est seul.
Il y a trois types de groupes :
– les groupes privés. On ne les "voit" pas dans la liste des groupes
– les groupes normaux
– les groupes normaux par défaut : ceux dans lesquels un nouvel utilisateur est intégré automatiquement.
Jelix 1.0.6
Guide du développeur
152 / 225

20.3.2 Classes utilitaires

Deux classes accompagnent le driver jAcl.db pour gérer les groupes, utilisateurs, droits etc : jAclDbManager et
jAclDbUserGroup (anciennement jAclManager et jAclUserGroup dans jelix 1.0beta2.1 mais leur fonctionnement n’a
pas changé).
Leur utilisation est similaire d’un point de vue théorique aux commandes de jelix-scripts (décrites dans Configurer
jAcl.db), aussi nous vous laissons lire la documentation de reference.

20.4 Configurer jAcl.db

Avant de pouvoir utiliser l’API de jAcl dans vos modules et le driver db de jAcl, il faut d’abord initialiser la base de
données, et mémoriser les différents éléments utilisés pour les droits.
La configuration est facilitée grâce aux scripts en ligne de commande fournis.

20.4.1 Création de la base

Le driver jAcl.db ne fonctionne qu’avec une base de données. Il vous faut donc configurer une connexion de base de
données, et créer les tables nécessaires.

Configuration de la connexion

Pour cela, il vous faut vous reporter à la page sur jDb.


Cependant, si les tables jAcl ne sont pas dans la base indiquée par le profil par défaut, il vous faut alors créer un
profil de connexion, et l’indiquer dans le parametre "jacl_profil". Un exemple de fichier dbprofils.ini.php :

default = foo
jacl_profil= acl

[foo]
driver="mysql"
database="jelix"
host= "localhost"
user= "jelix"
password= "jelix"
persistent= on
force_encoding=true

[acl]
driver="mysql"
database="droits"
host= "localhost"
user= "jelix"
password= "xilej"
persistent= on
force_encoding=true
Jelix 1.0.6
Guide du développeur
153 / 225

Création des tables

Vous trouverez dans le répertoire install/ du module jelix, des scripts sql pour créer les tables : install_jacl.schema.mysql.sql.
Vous devriez avoir alors les tables :
– jacl_group
– jacl_user_group
– jacl_right_values_group
– jacl_right_values
– jacl_subject
– jacl_rights
Une fois ces tables créées, vous pouvez vous lancer dans la configuration de jAcl.

20.4.2 Préparation

La configuration se fait au moyen de commandes du script jelix en ligne de commande. Ouvrez donc un terminal et
placez vous dans le répertoire lib/jelix-scripts.
$ cd lib/jelix-scripts/ # sous linux
$ cd lib\jelix-scripts\ # sous windows

(note : $ represente l’invité de commande).


Mémorisez ensuite le nom de votre appli dans la variable d’environnement JELIX_APP_NAME :
$ export JELIX_APP_NAME="myapp" # sous linux
$ set JELIX_APP_NAME=myapp # sous windows

Dans la suite, il faut exécuter le script jelix.php. Rappelez vous que l’on fait comme ceci, en appelant php :
$ php jelix.php une_commande argument argument argument...

Sous linux, vous avez un script bash qui facilite un peu les choses :
$ ./jelix une_commande argument argument argument...

Il y a trois commandes pour configurer jAcl.db : aclvalue, aclgroup et aclright. Chacune prenant en argument un nom
de "sous-commande" suivi de 0 à n arguments suivant la sous commande.

20.4.3 Création des valeurs

Dans le système de droit, vous devez déterminer des "sujets". Chacun de ces sujets pouvant être associés à une ou
plusieurs valeurs d’un ensemble de valeurs précises. Aussi, avant d’enregistrer les sujets, il faut créer ces groupes de
valeurs.
Dans l’ordre, on crée un groupe de valeur, et on enregistre ensuite toutes les valeurs possibles dans ce groupe.
Imaginons que l’on veuille créer un sujet "cms.articles", avec les valeurs READ, LIST, CREATE, DELETE, UP-
DATE.
On peut d’abord lister les groupes de valeurs qui existent :
$ php jelix.php aclvalue group_list

Au départ, vous devriez obtenir une liste vide :


Jelix 1.0.6
Guide du développeur
154 / 225

----Liste des groupes de valeurs de droits

id label key type


--------------------------------------------------------

Si il n’y a pas de groupe de valeurs existant correspondant à ce que vous voulez, il faut en créer un. Vous devez alors
indiquer un identifiant numérique (qui n’est pas déjà pris par un autre groupe), une clé de locale qui indiquera son
label (clé que vous devrez enregistrer dans un fichier de locale), ainsi que le type de groupe.
Si le sujet peut être associé à plusieurs valeurs du groupe (c’est notre cas dans l’exemple), le type est 0. Si il ne peut
être associé qu’à une seule valeur d’un groupe (par exemple, un groupe contenant "true" et "false"), le type est 1.
Créons notre groupe :
$ php jelix.php aclvalue group_add 1 "cms~acl.articles.values" 0

L’identifiant 1 et le nom de locale sont à modifier en fonction bien sûr de l’existant. Si vous n’utilisez pas de module
qui permette de gérer les droits, alors la clé de locale n’est pas indispensable. Mettez alors la chaîne que vous voulez.
À l’exécution de la commande, vous obtenez :
----Ajout d’un groupe de valeurs de droits

OK

Quand une commande acl se passe bien, il y a toujours le message OK. On peut le vérifier en listant à nouveau les
groupes :
$ php jelix.php aclvalue group_list
----Liste des groupes de valeurs de droits

id label key type


--------------------------------------------------------
1 cms~acl.articles.values 0 (combinable values)

Sachez que vous pouvez détruire un groupe de valeurs en faisant :


$ php jelix.php aclvalue group_delete 1

Maintenant il faut remplir le groupe avec des valeurs. On indique la valeur, une clé de locale pour le libellé de la
valeur, et l’id du groupe dans laquelle on la met.
$ php jelix.php aclvalue add READ "cms~acl.articles.value.read" 1
$ php jelix.php aclvalue add LIST "cms~acl.articles.value.list" 1
$ php jelix.php aclvalue add CREATE "cms~acl.articles.value.create" 1
$ php jelix.php aclvalue add DELETE "cms~acl.articles.value.delete" 1
$ php jelix.php aclvalue add UPDATE "cms~acl.articles.value.update" 1

On peut vérifier que tout est bien crée grâce à la sous commande list :
$ php jelix.php aclvalue list
----Liste des valeurs de droit

value label key


-----------------------------------------
GROUP 1 (cms~acl.articles.values)
CREATE cms~acl.articles.value.create
DELETE cms~acl.articles.value.delete
LIST cms~acl.articles.value.list
READ cms~acl.articles.value.read
UPDATE cms~acl.articles.value.update
Jelix 1.0.6
Guide du développeur
155 / 225

Vous pouvez bien sûr effacer une valeur avec la sous-commande delete, en indiquant la valeur et le numéro de groupe
de valeur. Par exemple :
$ php jelix.php aclvalue delete LIST 1

Vous pouvez maintenant créer autant de groupe de valeurs que nécessaire, sachant qu’un groupe de valeur peut être
bien sûr utilisé avec plusieurs sujets.

Tables concernées

– jacl_right_values_group, pour les groupes de valeurs.


– jacl_right_values, pour les valeurs.

20.4.4 Création des sujets

Maintenant que les valeurs sont créées, on va pouvoir créer les sujets. La gestion des sujets se fait au moyen de la
commande aclright. Créons notre sujet "cms.articles", en indiquant une clé de locale pour le libellé de ce sujet (ou
un libellé quelconque si vous n’utilisez pas de module de gestion de droits), ainsi que le groupe de valeur qui lui est
assigné (ici 1).
$ php jelix.php aclright subject_create "cms.articles" "cms~acl.articles.subject" ←-
1

vous pouvez ensuite vérifier la création de ce sujet :


$ php jelix.php aclright subject_list
----Liste des sujets

id label key
--------------------------------------------------------
cms.articles cms~acl.articles.subject
possible values: CREATE DELETE LIST READ UPDATE

Vous avez la possibilité de détruire un sujet en tapant :


$ php jelix.php aclright subject_delete "cms.articles"

Table concernée

– jacl_subject

20.4.5 Création des groupes d’utilisateurs

La déclaration d’un droit, nécessite un triplet valeur/sujet/groupe d’utilisateur. Nous devons donc créer un groupe
d’utilisateur. La gestion des groupes d’utilisateurs se fait au moyen de la commande aclgroup.
Créons par exemple un groupe de rédacteurs.
$ php jelix.php aclgroup create "rédacteurs"

Le message OK s’affiche, avec l’identifiant du nouveau groupe (ici 1) :


----Création d’un nouveau groupe

OK. Group id is: 1


Jelix 1.0.6
Guide du développeur
156 / 225

Nous allons en créer un deuxième, en indiquant avec l’option -defaultgroup que l’on veut que ce soit un groupe par
défaut, c’est à dire dans lequel sera mis tout nouvel utilisateur.
$ php jelix.php aclgroup -defaultgroup create "lecteurs"

On peut lister les groupes avec la sous-commande list :


$ php jelix.php aclgroup list
----Liste des groupes d’utilisateurs

id label name default


--------------------------------------------------------
2 lecteurs yes
1 rédacteurs

On peut changer le statut "default" plus tard, avec la sous commande setdefault :
$ php jelix.php aclgroup setdefault 1 true
ou
$ php jelix.php aclgroup setdefault 1 false

Il est aussi possible de changer le nom du groupe :


$ php jelix.php aclgroup changename 1 "super rédacteurs"

Ou encore d’effacer un groupe d’utilisateur :


$ php jelix.php aclgroup delete 1

Tables concernées

– jacl_group, pour les groupes d’utilisateurs.


– jacl_user_group, pour associer un utilisateur à un groupe.

20.4.6 Création des droits

Puisque nous avons maintenant tout ce qu’il faut pour définir des droits, définissons-en. On utilise la commande
aclright.
Déjà, pour les lecteurs, on va dire qu’ils peuvent lire et lister les articles. On va donc assigner les valeurs LIST et
READ pour le sujet "cms.articles", sur le groupe des lecteurs dont l’identifiant est 2 :
$ php jelix.php aclright add 2 "cms.articles" LIST
$ php jelix.php aclright add 2 "cms.articles" READ

Vérifions la liste des droits définis au moyen de la sous commande list :


$ php jelix.php aclright list
----Liste des droits

group subject value resource


---------------------------------------------------------------
- group lecteurs (2)
cms.articles
LIST
READ
Jelix 1.0.6
Guide du développeur
157 / 225

Passons maintenant au groupe rédacteur. On va leur donner tous les droits sur le sujet cms.articles.
$ php jelix.php aclright add 1 "cms.articles" LIST
$ php jelix.php aclright add 1 "cms.articles" READ
$ php jelix.php aclright add 1 "cms.articles" CREATE
$ php jelix.php aclright add 1 "cms.articles" DELETE
$ php jelix.php aclright add 1 "cms.articles" UPDATE

On vérifie :
$ php jelix.php aclright list
----Liste des droits

group subject value resource


---------------------------------------------------------------
- group lecteurs (2)
cms.articles
LIST
READ
- group rédacteurs (1)
cms.articles
CREATE
DELETE
LIST
READ
UPDATE

Imaginons qu’on veuille donner toutefois aux lecteurs le droit de modifier l’article "opinions", on créer alors un droit
sur la ressource "opinions", en indiquant l’identifiant de cette ressource en dernier paramètre à la sous commande
add :
$ php jelix.php aclright add 2 "cms.articles" UPDATE "opinions"

On vérifie :
$ php jelix.php aclright list
----Liste des droits

group subject value resource


---------------------------------------------------------------
- group lecteurs (2)
cms.articles
LIST
READ
UPDATE opinions
- group rédacteurs (1)
cms.articles
CREATE
DELETE
LIST
READ
UPDATE

On peut aussi retirer un droit avec la sous-commande remove, en indiquant, comme pour la sous-commande create,
le groupe d’utilisateur, le sujet, et la valeur conçernés (plus éventuellement la resource si on a une ressource).
Exemple, on change d’avis à propos de l’article "opinions" (il y a vraiment trop de spam :-) ) :
$ php jelix.php aclright remove 2 "cms.articles" UPDATE "opinions"
Jelix 1.0.6
Guide du développeur
158 / 225

Une fois tous les droits établis, l’application peut fonctionner selon vos rêgles, et les modules peuvent faire appels à
l’API de jAcl pour agir en fonction des droits que vous avez configuré.

Table concernée

– jacl_rights
Jelix 1.0.6
Guide du développeur
159 / 225

Chapitre 21

jLocale : internationaliser votre application

Jelix possède son propre mécanisme de localisation/internationalisation. Les fonctions setlocale et gettext de php ne
sont pas utilisées car trop contraignantes à mettre en place, et leur configuration est aléatoire sur les serveurs.

21.1 Principes

Chaque texte ou chaine que vous voulez traduire sont associés à une clé, un code. Ces associations sont stockés dans
des fichiers "properties". Chaque fichier properties étant attribués à une langue et un encodage de caractère. La langue
et l’encodage par défaut sont configurés dans le fichier de config de votre application : ce sont les paramètres locale
et charset, que vous pouvez récupérer en faisant
$lang = $GLOBALS[’gJConfig’]->locale;

Mais vous n’aurez pas à utiliser ce paramètre, sauf utilisation particulière. En effet, pour récupérer une chaine dans
la langue courante, il suffit d’appeler jLocale : :get(’selecteurDeLocale’), ou dans les templates d’utiliser la syntaxe
@selecteurDeLocale@ (voir la page sur les templates).

21.2 Fichiers properties

Ce sont des fichiers contenant des traductions. Ils sont situés dans le répertoire locales des modules. Ce répertoire
a une organisation spécifique. Il contient des sous répertoires pour chaque langue. Exemple :locales/fr_FR/, loca-
les/en_US/, etc. Et dans chacun de ces sous-répertoires, il y a les fichiers properties correspondant à la langue.

21.2.1 Noms des fichiers

Le nom des fichiers properties est structuré comme suit : codefichier.charset.properties. Codefichier est un nom de
code que l’on utilisera dans les sélecteurs, et charset correspond à un encodage de caractères. Exemple : foo.ISO-
8859-1.properties , foo.UTF-8.properties etc.
Si dans la configuration, "defaultLocale=fr_FR" et "defaultCharset=ISO-8859-1", alors ce sera le fichier fr_FR/foo.ISO-
8859-1.properties qui sera utilisé.
Jelix 1.0.6
Guide du développeur
160 / 225

21.2.2 Contenu des fichiers

La structure des fichiers est simple : il s’agit d’une suite de lignes cle=chaine traduite. Exemple, pour un fichier
fr_FR/foo.ISO-8859-1.properties :
title.offlineElements = éléments à traiter
title.onlineElements = éléments en ligne
buttons.save = Enregistrer
buttons.ok=Valider
buttons.cancel=Annuler
buttons.search=Rechercher

Et dans son équivalent anglais en_US/foo.ISO-8859-1.properties :


title.offlineElements = elements to check
title.onlineElements = online elements

buttons.save = Save
buttons.ok=Ok
buttons.cancel=Cancel
buttons.search=Search

Passage à la ligne

Si un texte est long et que vous voulez l’écrire sur plusieurs lignes, vous devez mettre un anti-slash (\) à la fin de
chaque retour à la ligne (sauf sur la dernière du texte)
intro=ceci est un très très\
long texte qui fait\
plusieurs lignes
foo=bar

Cependant, cela n’insère pas un saut de ligne (\n) dans la chaine.

Commentaires

Vous pouvez aussi mettre des commentaires. Ils doivent commencer par un # le reste de la ligne étant alors ignoré.
Vous pouvez mettre un commentaire en début de ligne ou à la suite d’une chaine traduite. De ce fait, si vous voulez
utiliser un # dans votre chaine, il faut précéder ce caractère par un "\".

Espaces

Il y a un "trim" qui est fait sur la chaine traduite, c’est à dire que les espaces avant et après sont supprimés. Si vous
voulez que la chaine soit un espace, vous utiliserez alors \w
foo= \w

Entités HTML

Les chaines localisées ne devraient pas contenir du code HTML. D’une part parce qu’une chaine localisée n’est
pas forcément destinée à être incluse dans du HTML, mais aussi parce que les réponses HTML échappent (htmlspe-
cialchars) à plusieurs endroits le contenu que vous lui donnez. De ce fait, les entités et autres signes HTML seront
Jelix 1.0.6
Guide du développeur
161 / 225

échappés. Si vous donnez par exemple une chaîne pour en faire le titre d’une page. Les entités ne seront donc pas
interprétées comme telles par le navigateur.
Si vous avez besoin d’utiliser des caractères spécifiques, choisissez l’encodage adéquate plutôt que de recourir aux
entités HTML. C’est pour cette raison qu’il est fortement encouragé d’utiliser l’encodage UTF-8, qui est d’ailleurs en
passe d’être l’encodage "universel" dans les applications web (en plus d’Unicode/UTF-16).

21.3 Récupération d’une chaîne localisée

Pour récupérer une chaîne, il faut utiliser la méthode statique get de jLocale. Cette méthode accepte en premier ar-
gument un sélecteur de locale, qui a cette structure : module~codefichier.clechaine. la partie "module~" est facultative
si il s’agit d’un fichier se trouvant dans le module courant.
Pour récupérer par exemple la valeur de buttons.save dans foo.ISO-8859-1.properties situé dans le module "bar" :
$chaine = jLocale::get("bar~foo.buttons.save");

Dans un template cela donnerait par exemple :


<input type="button" value="{@bar~foo.buttons.save@}" />

Note : pour l’utilisation dans les templates, voir les possibilités dans la page sur les templates

21.4 Chaine localisée avec paramètres

Il peut être utile d’avoir des chaines localisées dans lesquelles on veut insérer des valeurs dynamiquement. Par
exemple, imaginons que voulez écrire :
Vous allez sur le site http://foo.com et vous cliquez sur la rubrique voiture

Vous voulez pouvoir changer l’url du site et le nom de la rubrique. Vous pouvez alors passer les données en para-
mètres à jLocal :
$chaine = jLocale::get("bar~foo.phrase", array(’http://foo.com’, ’voiture’));

Et dans le fichier properties, vous mettez un %s partout où vous voulez insérer des valeurs dynamiques :
phrase = Vous allez sur le site %s et vous cliquez sur la rubrique %s

Et il faut donner les paramètres dans l’ordre d’apparition des %s. En fait, la chaine est traitée par la fonction sprintf
de php, donc vous avez toutes les possibilités syntaxiques de sprintf.
En particulier, il se peut que l’ordre d’insertion des paramètres change d’une langue à une autre. Plutôt donc que de
modifier l’ordre des paramètres quand vous appelez jLocale, vous indiquez quel paramètre va à quel endroit dans la
chaine localisée, au moyen de la syntaxe %x$s où x est un nombre d’ordre.
phrase = Vous allez sur le site %1$s et vous cliquez sur la rubrique %2$s

En anglais (même si ce n’est pas la véritable traduction, c’est juste pour l’exemple) ça pourrait donner ça :
phrase = Clic on the %2$s section, when you go on the %1$s web site.

Ainsi le premier paramètre ira à l’emplacement de %1$s, le deuxième à la place de %2$s etc...
Par contre, dans un template, vous ne pouvez pas utiliser la notion "@foo@" quand il faut des paramètres. Vous
devez alors utiliser le plugin jlocale :
<p>{jlocale "bar~foo.phrase", array(’http://foo.com’, ’voiture’)}</p>
Jelix 1.0.6
Guide du développeur
162 / 225

21.5 Changer la langue dynamiquement

Jelix fourni un plugin pour le coordinateur qui permet de changer la langue dynamiquement. C’est le plugin autolo-
cale (qui est situé dans lib/jelix/plugins/coord/). (voir la section sur les plugins de coordinateur).
Pour cela, le plugin regarde si un paramètre est présent dans l’url, indiquant la nouvelle langue à prendre en compte,
et utilisera cette langue durant le reste de la visite. En fait le nouveau code langue est stocké dans une variable de
session, et le plugin modifie l’option de configuration locale une fois la configuration lue (le fichier de configuration
n’est donc pas modifié).
Aussi c’est totalement transparent pour vous. Pour connaitre la langue à tout moment, il suffit de faire comme
d’habitude :
$lang = $GLOBALS[’gJConfig’]->locale;

Pour utiliser le plugin, copiez le fichier lib/jelix/plugins/coord/autolocale/autolocale.coord.ini.php.dist dans var/con-


fig/ en le renommant autolocale.coord.ini.php.
Les deux paramètres importants dans ce fichier sont :
enableUrlDetection= on
urlParamNameLanguage=lang
availableLanguageCode = fr_FR,en_US

Il faut bien sûr activer la détection de la langue dans l’url avec le paramètre enableUrlDetection. availableLangua-
geCode permet d’indiquer la liste des code des langues disponibles sur le site, ainsi les autres codes langues ne seront
pas possibles. Le paramètre urlParamNameLanguage contient le nom du paramètre de l’url qui contiendra le code
langue à utiliser. Aussi, vous pouvez mettre des liens sur votre site qui permettent à l’utilisateur de changer la langue.
Exemple :
<a href="index.php?lang=fr_FR">français</a>
<a href="index.php?lang=en_EN">english</a>

Bien sûr, si vous utilisez le moteur d’url significant, il est possible que vous définissiez des urls significatives spéci-
fiques pour chaque langue.
Enfin, il faut activer le plugin. Pour cela, dans la configuration de jelix, mettez dans la section plugins :
[plugins]
autolocale = autolocale.coord.ini.php

21.6 Détection automatique de la langue

Le plugin autolocale (voir paragraphe du dessus), permet aussi de détecter automatiquement la langue en fonction
du navigateur.
Pour cela, il suffit de mettre le paramètre useDefaultLanguageBrowser à on dans la configuration du plugin. Et
quand l’internaute arrive pour la première fois sur le site, le plugin détecte la langue utilisée dans son navigateur
et donc active la bonne langue dans jelix (si bien sûr, ce code langue est l’un de ceux que vous avez indiqués dans
availableLanguageCode).
Jelix 1.0.6
Guide du développeur
163 / 225

Chapitre 22

jEvents : communication inter-module

Jelix propose un système de communication inter-module sous forme d’évènements.


Il est possible d’émettre un évènement de n’importe quel endroit, et aux modules d’y répondre.
Pour cela, il y a d’une part un objet jEvent, permettant d’émettre un évènement et de récupérer les réponses, et
d’autre part, des "listener", qui sont des classes placées dans les modules, contenant les méthodes "répondant" aux
évènements.

22.1 Émettre un évènement

L’objet jEvent sert à la fois d’émetteur d’évènement, et en même temps de conteneur des réponses.
sa principale méthode, qui est statique, est notify :
$ev = jEvent::notify(’nom_evenement’, $parametre_event);

Elle accepte en paramètre un nom d’évènement (qui n’est constitué que de caractères alphanumériques), et un tableau
facultatif de paramètres (à utiliser selon l’évènement).
Vous recevez en retour l’objet jEvent instancié pour l’occasion, et contenant les réponses. Les réponses sont un
ensemble de valeurs dont la structure et le nombre dépend de l’évènement et du nombre de modules ayant répondu.
Pour avoir ces réponses :
$reponses = $ev->getResponse();

22.2 Répondre à un évènement

Pour qu’un module puisse répondre à un évènement, il faut créer un listener, et le déclarer dans le fichier events.xml
du module.

22.2.1 créer le listener

Il faut d’abord lui donner un nom. Foo par exemple, ensuite il faut créer une classe fooListener (se termine toujours
par "Listener"), héritant de jEventListener et stockée dans le fichier classes/foo.listener.php du module.
Cette classe contient une méthode pour chaque évènement auquel le listener répond. Ces noms de méthodes com-
mencent par "on" suivit du nom d’évènement. Et ces méthodes prennent en paramètre l’objet jEvent correspondant à
l’évènement. Exemple :
Jelix 1.0.6
Guide du développeur
164 / 225

class authListener extends jEventListener{

function onAuthCanLogin ($event) {


$user = $event->getParam(’user’);
$ok = true;
if(isset($user->actif)){
$ok = ($user->actif == ’1’);
}

$ok = $ok && ($user->password != ’’);

$event->Add(array(’canlogin’=>$ok));
}
}

Ce listener répond à l’évènement "AuthCanLogin". La méthode récupère le paramètre ’user’ de l’évènement. Et


ajoute une donnée dans la réponse ($event->add). Ce paramètre et cette donnée de réponse dépendent uniquement de
l’évènement AuthCanLogin. Pour d’autres évènements, il peut y avoir plusieurs paramètres ou aucun, d’autres types
de données de réponses ou aucune réponse.

22.2.2 Déclarer le listener

il faut ensuite déclarer le listener. Cela se fait dans un fichier events.xml placé à la racine du module. Voici un
exemple :
<events xmlns="http://jelix.org/ns/events/1.0">
<listener name="auth">
<event name="AuthCanLogin" />
<event name="FetchXulOverlay" />
</listener>
</events>

Vous mettez autant de balise listener que de listener stocké dans le répertoire classes du module. Et dans chacune
d’elles vous indiquez tous les évènements que prend en charge le listener, grâce à des balises event.
Jelix 1.0.6
Guide du développeur
165 / 225

Quatrième partie

Développement avancé
Jelix 1.0.6
Guide du développeur
166 / 225

Comment profiter des fonctionnalités avancées de Jelix ? comment développer des plugins de toutes sortes ?
Cette partie vous explique tout.
Jelix 1.0.6
Guide du développeur
167 / 225

Chapitre 23

Générer un contenu dans un format personna-


lisé

23.1 Créer un objet response

Il est possible que Jelix ne fournisse pas le moyen de générer du contenu dans un format spécifique voulu. Aussi, il
vous faut dans ce cas créer votre propre réponse.
Cela consiste à :
1. créer une classe héritant de jResponse (ou d’une autre réponse existante), et qui doit implémenter les méthodes
adéquates pour manipuler le format en question
2. de stocker cette classe dans le répertoire responses de votre application
3. de déclarer ce type de réponse dans le fichier de configuration

23.1.1 créer la classe

Une classe response doit posséder au moins deux méthodes : output() et outputErrors(). Et rédéfinir la propriété
$_type avec un identifiant propre à votre type de réponse. output() doit générer le contenu formaté correctement (en
faisant des print ou echo). outputErrors est appelé quand des erreurs bloquantes sont survenues pendant le traitement
d’une action. Il génère alors une réponse différente, voir spécifique au format dans ce contexte là. Il ne faut pas oublier
non plus d’envoyer un entête http correspondant au type de format.
Exemple d’un format (bidon :-) ) :

class myFooResponse extends jResponse {


protected $_type = ’foo’;

public $content = ’’;

/**
* génère le contenu et l’envoi au navigateur.
* @return boolean true si la génération est ok, false sinon
* /
public function output(){
global $gJConfig;
$this->_httpHeaders[’Content-Type’]=’text/foo;charset=’.$gJConfig-> ←-
defaultCharset;
Jelix 1.0.6
Guide du développeur
168 / 225

$this->sendHttpHeaders();
echo "content:\n".$this->content."/content;";
return true;
}

public function outputErrors(){


global $gJConfig;
header(’Content-Type: text/foo;charset=’.$gJConfig->defaultCharset);
echo "errors\n";
foreach( $GLOBALS[’gJCoord’]->errorMessages as $e){
echo ’[’.$e[0].’ ’.$e[1].’] ’.$e[2]." \t".$e[3]." \t".$e[4]."\n";
}
echo "/errors;";
}
}

Comme dans l’exemple ci-dessus avec la propriété $content, vous pouvez rajouter toutes les propriétés et méthodes
nécessaires à une manipulation aisé de l’objet dans les actions. Par exemple, l’objet jResponseHtml html instancie
d’office un template, contient une propriété pour spécifier le titre d’une page html, des méthodes pour ajouter des
choses dans le <head> etc..
N’hésitez pas à regarder le code source des fichiers dans lib/jelix/response/. Peut être d’ailleurs que votre format
s’apparente à un de ceux fournis par Jelix. Dans ce cas, votre objet response peut hériter de cet objet, ajouter des
méthodes, en redéfinir etc.

23.1.2 Stockage de la classe

Le nom de la classe importe peu, mais il doit être utilisé dans le nom du fichier, et précède le suffixe ’.class.php’.
Dans notre exemple, la classe sera alors stockée dans le fichier myFooResponse.class.php.
Le fichier doit être enregistré dans le répertoire responses de votre application.

23.1.3 Déclarer la réponse

Pour que la réponse soit utilisable par les actions, il faut la déclarer avec un code. Et c’est ce code que vous indiquerez
à la méthode getResponse dans les contrôleurs. Pour cela, vous ajouterez dans la section responses du fichier de
configuration, une ligne code=classe.
[responses]
foo=myFooResponse

Et dans un contrôleur, cela donne :

function index(){
$rep = this->getResponse(’foo’);
$rep->content=’hello world’;
return $rep;
}

Pourquoi ne pas indiquer directement le nom de la classe à getResponse ? Parce que cela permet de redéfinir un
même type de réponse de façon transparente pour les actions et modules.
Jelix 1.0.6
Guide du développeur
169 / 225

23.1.4 À propos des templates

Les plugins de templates sont, pour un certain nombre, attribués à un type de réponse particulier. Aussi, si vous créer
un nouveau type de réponse spécifique, il vous faudra adapter aussi dupliquer/copier/recréer les plugins de templates
existants pour les autres types de réponses.
Si vous héritez par contre d’un objet response existant (de jResponseHtml par exemple), ne changez pas la propriété
type de la classe mère, sinon vous ne pourrez pas réutiliser les plugins de templates existants (à moins de les redefinirs).
Voir la doc pour faire des plugins de templates.
Jelix 1.0.6
Guide du développeur
170 / 225

Chapitre 24

Système de thèmes

Jelix propose un système de thèmes, permettant donc de personnaliser les templates et les feuilles de style, sans
toucher aux fichiers originaux.

24.1 Les templates d’un thème

Un thème est un répertoire dans var/themes/. Ce répertoire contient des fichiers templates dans des sous-repertoires
qui correspondent à chaque module.
Par exemple, vous voulez adapter le template main.tpl du module exemple, pour le thème web20, vous stockerez un
fichier main.tpl dans var/themes/web20/exemple/. Notez donc que le template original et le nouveau template possède
le même nom.
Le thème par défaut ayant pour nom "default", si vous voulez redéfinir un template d’un module, même si vous
n’utilisez pas explicitement les thèmes, vous placerez ce template dans var/themes/default/le_module/le_template.tpl.

24.2 Les fichiers web d’un thème

Par fichier web, on entend les fichiers CSS, les images etc... Ces fichiers ne doivent pas être placé dans var/themes/
car var n’est pas censé être accessible publiquement depuis le web.
Vous les placerez donc dans un répertoire themes/le_nom_du_theme/ dans le répertoire de base de votre application
(basePath), en général donc dans www/
Pour avoir le chemin web du theme, vous pouvez utiliser ceci :
$chemin = $gJConfig->urlengine[’basePath’].’themes/’.$gJConfig->theme.’/’
$rep->addCssLink($chemin.’design.css’);

Dans un template, vous avez une facilité en utilisant la balise meta :


{meta_html csstheme ’design.css’}

D’autres sont disponibles pour les feuilles de styles spéciales pour IE


{meta_html cssthemeie ’design.css’} pour ie
{meta_html cssthemeie7 ’design.css’} pour ie7
{meta_html cssthemeltie7 ’design.css’} pour ie < 7
Jelix 1.0.6
Guide du développeur
171 / 225

Mais vous avez aussi une variable déclarée automatiquement, j_themepath, dans un template contenant le chemin
des thèmes
<img src="{$j_themepath}logo.png" alt="logo"/>

24.3 Déclarer un thème par défaut

L’activation d’un thème se fait dans le fichier de configuration, au niveau du paramètre theme :
theme = web20

24.4 Déclarer un thème dynamiquement

Pour offrir la possibilité à l’internaute de choisir son thème, vous pouvez lui proposer un formulaire avec la liste des
themes (liste que vous construisez vous même).
Ensuite vous stockez le nom du thème choisi quelque part (en session, ou dans un cookie par exemple).
Enfin, pour que le thème soit activé automatiquement, il suffit de récupérer le nom du theme correspondant à l’utili-
sateur, et de le spécifier dans la configuration, au niveau du paramètre theme :
$GLOBALS[’gJConfig’]->theme = $themeChoisi;

Bien sûr, le meilleur endroit pour faire ça est dans un plugin de coordinateur qu’il vous faut développer.
Jelix 1.0.6
Guide du développeur
172 / 225

Chapitre 25

Surcharge de fichiers de modules

Il peut arriver que vous utilisiez un module fourni par un tiers, et que certains fichiers ne vous conviennent pas tout
à fait. Plutôt que de les modifier directement, Jelix propose un moyen de redéfinir ces fichiers sans les toucher. Cela
permet plus tard de mettre à jour ce module tiers sans écraser vos modifications.
Les fichiers d’un module que vous pouvez redefinir sont :
– les templates, par le biais de thèmes
– les fichiers de locales
– les fichiers daos
– les fichiers forms
Pour les thèmes, voir la page spécifique. Le thême par défaut se nommant "default", il suffit de mettre les nouveaux
templates dans le répertoire de ce thème.
Pour les autres types de fichiers, il faut mettre les nouveaux fichiers dans le répertoire var/overloads/. Ce réper-
toire contient des sous-répertoires ayant les noms des modules. Ces sous-répertoires sont alors organisés comme les
modules.
Par exemple, imaginons que vous voulez redefinir des fichiers du module exemple.
– vous placerez les daos dans var/overloads/exemple/daos/
– vous placerez les forms dans var/overloads/exemple/forms/
– vous placerez les locales dans var/overloads/exemple/locales/
Les noms des fichiers doivent être les mêmes que les originaux. Pour les daos, n’oubliez pas de respecter l’api du
dao original. C’est à dire que si des méthodes sont définis dans le dao original, il faut aussi les définir dans le nouveau
fichier, sinon vous risquez d’avoir des erreurs PHP parce que les classes du module ne pourront appeler les-dites
méthodes.
Ensuite c’est tout. Le fait de mettre un fichier dans le répertoire var/overloads/ redéfini automatiquement le fichier
original correspondant. Ce sera ce nouveau fichier qui sera utilisé et non pas l’original.
Jelix 1.0.6
Guide du développeur
173 / 225

Chapitre 26

Développer et utiliser des plugins

Il existe toutes sortes de plugins pour ajouter des fonctionnalités à diverses parties de Jelix. On peut ainsi ajouter
des plugins pour le coordinateur, des drivers pour jDb, des drivers pour jAuth, des plugins pour jTpl ou encore des
nouveaux moteurs d’URLs.
Tous les plugins sont regroupés dans des dépôts de plugins (note : ce n’était pas le cas dans jelix 1.0beta2 et inférieur).

26.1 Déclaration d’un dépôt de plugins

Vous pouvez déclarer un ou plusieurs dépôts de plugins. Un dépôt est un répertoire ayant une structure précise (voir
plus loin). Il faut déclarer chacun de ces dépôt dans le paramètre pluginsPath de la configuration de l’application. Par
défaut, ce paramètre vaut :
pluginsPath = lib:jelix-plugins/,app:plugins/

Vous remarquez que vous pouvez indiquer plusieurs dépôts, séparés par une virgule. Ici il est indiqué qu’il y a deux
dépôts : le répertoire jelix-plugins dans le répertoire lib/, et un répertoire plugins dans votre application. Il y en a un
troisième, implicitement et automatiquement déclaré, qui est le répertoire lib/jelix/plugins/ et contenant les plugins
livrés en standard avec Jelix.
Rappel : lib : est un raccourci indiquant le répertoire de base lib/, et app : un raccourci pour le répertoire de votre
application. Vous pouvez aussi indiquer un chemin absolu. Attention toutefois si vous migrez votre application d’une
machine à une autre. Il est aussi possible d’utiliser un chemin relatif, mais celui-ci doit être relatif au script de point
d’entrée (index.php par ex).

26.2 Structure d’un dépôt et création de plugins

Un dépôt de plugins contient un répertoire pour chaque type de plugins et dans chacun de ces répertoires, un réper-
toire pour chaque plugin.
Voici les types de plugins et les répertoires correspondant :
– plugins de coordinateur : coord/
– drivers pour jAuth : auth/
– drivers pour jDb : db/
– plugins de templates : tpl/
– moteurs d’URLs : urls/
Note : Pour les version 1.0beta2 ou inférieur, la notion de plugin était restreinte aux seuls plugins pour le coordinateur.
Aussi les dépôts de plugins ne contenaient que des plugins pour le coordinateur. Ceux-ci n’étaient pas placés dans un
sous-répertoire coord/, mais directement dans le dépôt.
Jelix 1.0.6
Guide du développeur
174 / 225

26.3 Création de plugins

Jelix fournit en standard un certain nombre de plugins dans le dépôt lib/jelix/plugins/. Cependant, il est souvent
nécessaire de devoir en créer pour ses propres besoins. D’ailleurs toute contribution de nouveaux plugins est vivement
encouragée ;-)
Les sections suivantes vous indiquent comment développer ces plugins.

26.4 plugins de coordinateur

Il est possible d’ajouter des plugins au coordinateur (le coeur de Jelix, jCoordinator) qui permettent de faire des
traitements supplémentaires à différentes étapes de l’exécution d’une action, quelle que soit cette action.
Il est ainsi possible d’effectuer un traitement au démarrage du processus, juste avant l’exécution de l’action, juste
après (avant affichage), et en fin de processus.
Les plugins pour le coordinateur sont aussi appelés plugins coord dans le jargon Jelix.

26.4.1 Utilisation d’un plugin coord

Déclaration

Pour activer un plugin coord, vous avez deux choses à faire dans le fichier de configuration d’un point d’entrée :
– bien sûr, déclarer le dépôt contenant le répertoire de votre plugin, dans l’option pluginsPath de la configuration
– indiquer le plugin dans la section [plugins], ainsi que son éventuel fichier de configuration
Si vous placez votre plugin foo dans votreApplication/plugins/coord/ alors vous devez déclarer comme ceci :
pluginsPath = app:plugins/

[plugins]
foo = foo.coord.ini.php

Ici on indique un fichier de configuration foo.coord.ini.php pour le plugin (le contenu et la structure de ce fichier de
configuration dépend totalement du plugin). Dans le cas où votre plugin ne comporte pas de fichier de configuration,
vous devez mettre 1 au lieu d’un nom de fichier, comme ceci :
foo = 1

Si vous utilisez plusieurs plugins de coordinateur, l’ordre de déclaration des plugins dans le fichier de configuration a
une importance. Ainsi le premier plugin déclaré à la priorité sur les autres. C’est à dire que si ce premier plugin renvoi
une action, les autres plugins ne seront pas exécutés. Il convient donc de choisir l’ordre de déclaration des plugins en
fonction de la priorité que l’on veut pour chaque plugin. Par exemple si vous considérez que le plugin bar ne peut être
exécuté que si le plugin foo n’a pas renvoyé d’action, alors il faudrait les déclarer comme ceci :
[plugins]
foo = foo.plugin.ini.php
bar = 1

Configuration

Un plugin coord peut avoir besoin d’un fichier de configuration. Ce fichier doit être alors un fichier de type ini, placé
dans votreApplication/var/config/ et être déclaré dans la configuration comme indiqué précédemment. Le contenu ini
sera passé au constructeur du plugin sous forme de tableau (résultat de la fonction php parse_ini_file).
Jelix 1.0.6
Guide du développeur
175 / 225

Paramètres de plugins

Certains plugins coord peuvent attendre des paramètres qui sont fournis par les contrôleurs. En effet, un plugin peut
vouloir tester quelque chose en fonction de l’action. Par exemple, le plugin coord d’authentification auth va vérifier si
l’action demandée nécessite ou non d’être authentifié. Pour cela, on va indiquer dans chaque contrôleur un paramètre
pour chaque action, destiné au plugin auth, qui indique cette information.
Ces paramètres sont stockés dans la propriété pluginParams du contrôleur. C’est un tableau associatif. Les clés sont
les noms des méthodes, et les valeurs, un tableau contenant tous les paramètres de plugins associés à la méthode (et
donc à l’action correspondante). Une clé particulière, ’*’, indique les paramètres valables pour toutes les méthodes du
contrôleur.
Exemple :

public $pluginParams = array(


’*’=>array(’auth.required’=>false)
);

Indique que toutes les actions du contrôleur ont un paramètre nommé "auth.required" et valant false.

26.4.2 Développement d’un plugin coord

Un plugin est en fait une classe qui implémente l’interface jICoordPlugin. Cette classe doit donc implémenter les
méthodes suivantes :
public function __construct($config);
public function beforeAction($params);
public function beforeOutput();
public function afterProcess ();

Le constructeur reçoit la configuration du plugin.


La méthode beforeAction reçoit les paramètres de plugins déclarés dans le contrôleur. Elle peut renvoyer null si tout
est ok ou alors un sélecteur d’action, jSelectorAct, si il faut exécuter une autre action que celle prévue.
La méthode beforeOutput sera appelée après exécution de l’action.
Le méthode afterProcess sera appelée en fin de traitement (après affichage donc).
Cette classe est à placer dans un dépôt de plugins. Par exemple, le répertoire plugins/ de votre application. Ou alors
dans un répertoire plugins/ d’un module. Le sous répertoire dans lequel est placé le plugin doit porter le nom du
plugin, et la classe doit suivre un nommage particulier. Si le plugin s’appelle exemple, alors :
– le répertoire du plugin sera plugins/coord/exemple/
– le fichier contenant la classe du plugin devra être plugins/coord/exemple/exemple.coord.php
– le nom de la classe du plugin devra être exempleCoordPlugin, implémentant l’interface jICoordPlugin

26.5 drivers pour jAuth

Si les drivers standards pour jAuth ne vous conviennent pas, vous pouvez donc en créer un. Voici comment.
Jelix 1.0.6
Guide du développeur
176 / 225

26.5.1 Création

Un driver est une classe qui respecte l’interface jIAuthDriver, qui reprend à peu de chose près l’API de jAuth (mais
ne dérive pas de jAuth).
Ces drivers sont appelés par jAuth. Ils font les opérations de "bas" niveau (accès base de données, ou à un annuaire
ldap, ou à un fichier texte etc...)
Soit exemple le nom de votre driver, vous devez créer une classe exempleAuthDriver, dans un fichier exemple.auth.php,
et placer celui-ci dans un répertoire auth/exemple/ dans un dépôt de plugins.

26.5.2 Activation

Pour utiliser votre nouveau driver, vous devez indiquer "exemple" au niveau de l’option "driver" du fichier de
configuration du plugin auth, et avoir une section "exemple" suivit des éventuelles options spécifiques au driver.
Exemple :
driver=exemple

[exemple]
foo=bar

26.6 drivers pour jDb

jDb, la couche d’abstraction d’accés aux bases de données, a un système de plugin, ou "drivers". Un driver permet
d’accéder à un type de base de donnée spécifique.

26.6.1 Activation

Pour savoir comment activer un driver pour jDb, voyez le chapitre sur jDb

26.6.2 Création d’un driver

Un driver pour jDb est constitué de trois classes :


– une classe pour la connexion à la base et l’exécution des requêtes, héritant de jDbConnection
– une classe pour récupérer les résultats, héritant de jDbResultSet
– une classe utilitaire héritant de jDbTools, permettant de récupérer la liste des tables, la liste des champs d’une table
etc..

Fichiers et nommages

Un driver possède un nom identifiant. Prenons le nom "exemple" pour la suite.


Les fichiers du driver doivent se trouver dans un répertoire db/exemple dans un dépôt de plugins.
Les noms des fichiers doivent suivre ce nommage :
– exemple.dbconnection.php pour la classe de connexion
– exemple.dbresultset.php pour la classe de resultset
– exemple.dbtools.php pour la classe utilitaire
Jelix 1.0.6
Guide du développeur
177 / 225

Et dans chacun de ces fichiers, les classes doivent respectivement avoir le nommage suivant :
– exempleDbConnection
– exempleDbResultSet
– exempleDbTools

Classe de connexion

Elle doit hériter de jDbConnection qui contient quelques méthodes abstraites qu’il faut définir. Son rôle est de se
connecter/déconnecter à la base de donnée. Elle est chargée aussi d’initier les transactions et de les confirmer ou
annuler. Enfin, elle exécute ou prépare les requêtes, en renvoyant un objet résultat.
Pour se faire, elle doit redéfinir les méthodes suivantes :
– le constructeur si il y a besoin de faire des choses à l’instanciation du driver. Typiquement, vérifier que les fonctions
PHP nécessaires sont bien là.
– _connect() et _disconnect(), pour la connexion et la déconnexion à la base de donnée
– _quote, pour échapper une chaîne de caractère avant que celle-ci soit utilisée dans une requête
– _doQuery et _doLimitQuery, pour lancer des requêtes qui ramènent des enregistrements (SELECT ou procédures
stockées). Elles doivent renvoyer un objet exempleDbResultSet ou false si la requête a échoué
– _doExec, pour lancer des requêtes ne renvoyant pas d’enregistrements (UPDATE, DELETE, INSERT...). Doit
renvoyer le nombre d’enregistrements affectés, ou false si la requête a échoué
– la méthode prepare(), pour préparer les requêtes.
– beginTransaction(), commit(), rollback(), pour les transactions
– errorInfo() et errorCode() renvoyant l’intitulé et le code de la dernière erreur
– lastInsertId(), permettant de récupérer la dernière valeur du dernier id autoincrémenté généré.
– _autoCommitNotify()
Si le driver ne prend pas en charge certaines fonctionnalités, il doit générer une exception.
Voir la référence de jDbConnection pour plus de détails.

Classe de résultat

Elle doit hériter de jDbResultSet qui contient quelques méthodes abstraites qu’il faut définir. Un objet de cette classe
est normalement renvoyé par les méthodes prepare, _doQuery et _doLimitQuery de la classe exempleDbConnection.
Vous devez notament redéfinir les méthodes suivantes :
– _fetch(), qui doit récupérer l’enregistrement suivant dans la liste des résultats. Elle doit tenir compte de la propriété
_fetchMode. Dans la propriété _idResult, vous trouverez l’identifiant de la ressource liée aux résultats.
– _free(), pour libérer la ressource liée aux résultats (_idResult)
– _rewind(), pour revenir au début des résultats
– rowCount, pour retourner le nombre de résultats
– bindColumn, bindParam, bindValue, columnCount et execute pour les requêtes préparées.
Voir la référence de jDbResultSet pour plus de détails.

Classe utilitaire

Elle doit hériter de jDbTools. Cette classe permet de récupérer des informations sur la base de donnée, sur une table
etc. Utilisée notamment par les scripts jelix-scripts.
Vous redéfinirez en particulier les méthodes suivantes :
– _getTableList(), retournant un tableau contenant les noms des tables présentes
Jelix 1.0.6
Guide du développeur
178 / 225

– _getFieldList(), retournant la liste des champs de la table dont le nom est donné en argument. Cette liste doit être
constitué d’objets jDbFieldProperties.
– execSQLScript() si vous voulez redéfinir la manière dont est parsé et executé un ensemble de requêtes SQL
présentes dans un script.
Voir la référence de jDbTools pour plus de détails.

Exemples

Voir les drivers pour mysql, postgresql etc dans le répertoire lib/jelix/plugins/db/.

26.7 plugins de templates

Vous pouvez ajouter vos propres fonctionnalités de templates dans le moteur de template jTpl. Elles doivent être
implémentées dans un plugin de template. Il y a quatre types de plugin :
– les fonctions
– les modificateurs
– les blocs
– les meta
Regardez dans lib/jelix/plugins/tpl/, vous avez plein d’exemples relativement simples à comprendre.

26.7.1 Emplacement

Les plugins sont stockés dans un répertoire ayant une arborescence précise : ils sont classés dans des sous-répertoires
en fonction du type de réponse auxquels ils sont destinés. Cela évite ainsi d’utiliser des plugins pour le XUL quand
on fait du HTML par exemple.
C’est ainsi que dans un dépôt de plugin de template, vous avez un sous répertoire "html", "xul", "text" et "common".
Le sous-répertoire "common" est celui dans lequel sont mis les plugins qui ne sont pas destinés à des types de réponses
précis.
lib/jelix/plugins/tpl/ est le dépôt par défaut de jelix pour les plugins de template. Mais vous mettrez en général vos
propres plugins de template dans le répertoire plugins/ de votre application, ou dans un autre dépôt à votre convenance
(dépôt à déclarer, comme indiqué sur la page des plugins). Sachant que dans le dépôt en question, il vous faut mettre
comme indiqué précédemment vos plugins dans tpl/common/, tpl/html/, ou tpl/text/ etc...

26.7.2 plugin type "function"

Ce sont des plugins que l’on pourra appeler comme ceci :


{mafonction $param1,$param2}

En admettant que c’est un plugin uniquement pour html, vous créerez un fichier function.mafonction.php dans
tpl/html/, dans lequel vous déclarez une fonction "jtpl_function_html_mafonction". Cette fonction prend au moins
un paramètre : l’objet jTpl qui est utilisé pour le template, et que vous pouvez donc manipuler à loisir. Les autres
paramètres sont ceux qui sont indiqués dans le template. La fonction ne doit rien renvoyer.
Dans la fonction, vous faites ce que vous voulez. En général, une fonction affiche quelque chose, donc effectue des
"echo".
Exemple, le plugin zone :
Jelix 1.0.6
Guide du développeur
179 / 225

function jtpl_function_html_zone($tpl, $name, $params=array())


{
echo jZone::get($name, $params);
}

26.7.3 plugin type "cfunction"

Ce sont des plugins qui s’utilisent comme un plugin de fonction (donc du point de vue de l’utilisateur, il n’y a pas
de changement), mais qui ne sont pas programmés de la même manière. Contrairement à un plugin function qui est
toujours appelé lors de l’affichage ou plutôt de l’évaluation du template, un plugin cfunction est appelé bien avant,
lors de la compilation du template. Pour rappel, un template est d’abord transformé en contenu php (la compilation),
ce contenu php est stocké dans un fichier de cache, et il est ensuite évalué lorsque l’on veut afficher le template.
Un plugin cfunction ne génère donc pas un contenu, mais génère du code PHP qui sera inclus dans le contenu PHP
mis en cache. Cela est nécessaire dans certains cas, et peut améliorer les performances dans d’autres.
un plugin cfunction doit accepter en paramètre un objet jTplCompiler, et un tableau contenant les paramètres indiqués
dans le template. Vous ne devez en général pas toucher à ces paramètres, juste les inclure directement dans le code
PHP que va générer le plugin. Le plugin ne doit rien afficher, et doit retourner le contenu généré.
Voici l’exemple d’un plugin cfunction , qui fait au final la même chose que l’exemple de plugin function précédent :
function jtpl_cfunction_html_zone($compiler $params=array())
{
if (count($params) < 1 || count($params) > 2) {
$compiler->doError2(’errors.tplplugin.cfunction.bad.argument.number’,’zone ←-
’,’1-2’);
}

if (count($params) == 1) {
$php = ’ echo jZone::get(’.$params[0].’);’;
}
else {
$php = ’ echo jZone::get(’.$params[0].’, ’.$params[1].’);’;
}
return $php;
}

26.7.4 plugin type "modifier"

Un plugin modificateur est une fonction jtpl_modifier_monmodificateur prenant une chaine en paramètre (et even-
tuellement d’autres pour ceux qui ont besoin de paramètre de modificateur, voir plus haut), et renvoie une chaine
transformée. La fonction doit être stockée dans un fichier de nom modifier.monmodificateur.php.
Exemple avec le plugin count_characters :
function jtpl_modifier_html_count_characters($string, $include_spaces = false)
{
if ($include_spaces)
return(strlen($string));

return preg_match_all("/[^\s]/",$string, $match);


}
Jelix 1.0.6
Guide du développeur
180 / 225

26.7.5 plugin de bloc

Comme les plugins de type cfunction, les plugins de blocs ne sont pas appelés lors de l’affichage du template, mais
lors de sa compilation. Un plugin de bloc ne renvoie donc pas une valeur transformée, ne fait pas d’affichage, mais
renvoie du code php, qui sera inclus dans la version compilée du template.
Ils permettent de se faire ses propres structures if ou boucle, ou autre blocs spéciaux.
Un plugin de bloc est une fonction jtpl_block_html_monbloc, qui accepte en paramètre un objet jTplCompiler, un
booléen et d’éventuels autres paramètres. La fonction doit être stockée dans un fichier block.monbloc.php.
La fonction est appelée par le compilateur, une première fois quand il rencontre le tag de début, et une deuxième fois
quand il rencontre le tag de fin. Le booléen en paramètre permet de savoir à quel moment la fonction est appelée (true
quand il s’agit de la première fois).
Exemple du plugin ifuserconnected :
function jtpl_block_ifuserconnected($compiler, $begin, $params=array())
{
if($begin){
if(count($params)){
$content=’’;
$compiler->doError1(’errors.tplplugin.block.too.many.arguments’,’ ←-
ifuserconnected’);
}else{
$content = ’ if(jAuth::isConnected()){’;
}
}else{
$content = ’ } ’;
}
return $content;
}

26.7.6 plugin meta

Un plugin meta est appelé lors de l’évaluation d’un template, mais juste avant l’affichage. En effet, lors de l’évalua-
tion, il y a deux phases, l’une qui permet de faire des choses avant l’affichage, puis l’affichage proprement dit. Cette
phase de pré-affichage est généralement utilisée pour modifier des propriétés de l’objet response courant. Par exemple,
pour une réponse HTML, un template sert uniquement à générer la partie "body" d’une page html. Si on veut, dans le
HTML, spécifier des choses du genre, liens css ou script JS à lier (donc concrétement à rajouter des choses au niveau
de la balise head), il faut le faire pendant le pré-affichage. Et les plugins meta sont appelés pendant cette phase, grâce
à l’instruction {meta ...}.
à compléter.. (voir le plugin lib/jelix/plugins/tpl/html/meta.html.php pour un exemple).

26.8 moteurs de urls

jUrl peut utiliser le moteur d’urls de votre choix.

26.8.1 Activation

Pour activer un plugin d’url, il faut d’abord le placer dans un répertoire portant son nom, dans un répertoire "urls"
d’un dépôt de plugin.
Jelix 1.0.6
Guide du développeur
181 / 225

Ensuite, dans la section urlengine du fichier de configuration principal, vous indiquez le nom du moteur d’url dans
le paramètre "engine". Ensuite, selon le moteur d’urls, il peut y avoir d’autres choses à paramétrer.

26.8.2 Création

À documenter. En attendant, regarder les moteurs existants dans lib/jelix/plugins/urls.


Jelix 1.0.6
Guide du développeur
182 / 225

Chapitre 27

La configuration en détails

27.1 Points d’entrée

Un point d’entrée est un script par lequel passe une partie ou toutes les actions. Seuls les points d’entrée sont en
principe accessible depuis le web, donc dans le répertoire www de l’application.
Ce sont eux qui instancient un objet jCoordinator, un objet de type jRequest qui analysera la requète et qui indiquent
le fichier de configuration à utiliser.
Un point d’entrée contient un bout de code comme celui-ci :
// chargement du fichier principal de jelix
require_once (’../../lib/jelix/init.php’);

// chargement du fichier d’initialisation de l’application


require_once (’../../testapp/application.init.php’);

// le fichier de configuration à utiliser


$config_file = ’index/config.ini.php’;

// instanciation du coordinateur

$jelix = new jCoordinator($config_file);

// instanciation d’un objet de type jRequest


require_once (JELIX_LIB_CORE_PATH.’request/jClassicRequest.class.php’);
$request = new jClassicRequest();

// execution de l’action
$jelix->process($request);

Il y aura en principe un point d’entrée pour chaque type de requête : classique, XML-RPC, JSON-RPC, RSS, Atom
etc..
Et donc il y aura en général une configuration spécifique à chaque point d’entrée.

27.2 Organisation de la configuration

La configuration du framework est stockée dans un fichier de type "ini". Il s’agit d’un fichier contenant des sections,
débutant par un nom entre crochet. Chacune de ces sections contenant une série de paramètres "nom=valeur". Il y a
Jelix 1.0.6
Guide du développeur
183 / 225

une section "générale", qui n’a pas de nom, et dont les paramètres sont en début du fichier.
Les fichiers de configurations sont situés dans var/config.
Chaque point d’entrée peut avoir son fichier de configuration spécifique. Mais la plupart du temps ils ont beaucoup
de valeurs de paramètres identiques entre eux. Pour éviter de répéter ces paramètres identiques dans chaque fichier, il
y a un fichier de configuration commun, qui a pour nom defaultconfig.ini.php. Il est automatiquement lu, en plus du
fichier spécifique au point d’entrée, et il n’est pas besoin de l’indiquer dans les points d’entrée.
Un fichier de configuration spécifique ne contiendra donc que les valeurs spécifiques pour le point d’entrée, et peut
bien sûr redéfinir des paramètres définis dans le fichier commun.
Exemple d’un fichier defaultconfig.ini.php (extrait) :
locale = "fr_FR"
charset = "ISO-8859-1"
timeZone = "Europe/Paris"
theme = default

checkTrustedModules = off

; list of modules : module,module,module


trustedModules =

pluginsPath = lib:jelix-plugins/,app:plugins/
modulesPath = lib:jelix-modules/,app:modules/

dbProfils = dbprofils.ini.php

[plugins]
;nom = nom_fichier_ini

[responses]
...

Pour les requêtes classiques, passant par index.php, on pourrait avoir le fichier var/config/index/config.ini.php. On
le met ici dans un sous répertoire index pour une meilleure organisation (il peut en effet y avoir des fichiers de
configuration de plugins propre à chaque point d’entrée, ça peut donc vite devenir peu lisible dans var/config/).
Dans ce fichier, on ne va redéfinir que certaines choses :
startModule = "testapp"
startAction = "main:index"

[plugins]
autolocale = index/autolocale.ini.php

[responses]
html=myHtmlResponse

Pour le fichier de configuration de xmlrpc.php, on pourrait avoir par exemple :

startModule = "testapp"
startAction = "xmlrpc:index"

etc.
Jelix 1.0.6
Guide du développeur
184 / 225

27.3 Déscriptif des sections de la configuration

Pour avoir la liste complète des options, voir le fichier lib/jelix/core/defaultconfig.ini.php, qui est "l’original" de la
copie que vous devez avoir dans var/config/.
Voici les différentes sections.

27.3.1 section générale

Ce sont les paramètres situés en début de fichier. Ils définissent des valeurs par défaut ou génériques à l’application.
startModule = "jelix"
startAction = "default:index"
locale = "fr_FR"
charset = "UTF-8"
timeZone = "Europe/Paris"

checkTrustedModules = off

; list of modules : module,module,module


trustedModules =

pluginsPath = lib:jelix-plugins/,app:plugins/
modulesPath = lib:jelix-modules/,app:modules/

dbProfils = dbprofils.ini.php

theme = default
use_error_handler = on

enableOldActionSelector =

Détails des paramètres :


– startModule, startAction : module et action par défaut (redéfinis en général pour chaque type de réponse. Voir la
section précédente)
– locale, charset : langue et encodage par défaut des réponses
– timeZone : défini le décalage horaire pour toutes les fonctions de dates et heures
– checkTrustedModules, trustedModules et modulesPath : options concernant les modules
– pluginsPath : liste des chemins d’accès aux plugins
– dbProfils : fichier de configuration des profils d’accès aux bases de données. Voir l’accès aux bases de données
– theme : nom du thème sélectionné par défaut. Voir la description du système des thèmes de Jelix
– use_error_handler : cette option devrait rester à on pour que Jelix retourne des informations pertinentes sur les
erreurs et exceptions des scripts.
– enableOldActionSelector : affecter la valeur 1 pour garder une compatibilité avec les sélecteurs d’action de Jelix
version 1.0 beta3 et antérieures. Pour les versions ultérieures, ce paramètre n’est pas nécessaire.

27.3.2 section plugins

Doit contenir les noms des plugins à activer. Ils seront chargés à partir des chemins définis dans le paramètre général
pluginsPath.
Par exemple, ci-dessous la configuration active le plugin de coordinateur gérant l’authentification et dont les para-
mètres se trouve dans le fichier auth.coord.ini.php. Pour plus de détails, voir la documentation sur l’authentification
Jelix 1.0.6
Guide du développeur
185 / 225

[plugins]
;nom = nom_fichier_ini
auth = "auth.coord.ini.php"

27.3.3 section responses

Cette section permet de personnaliser les types réponses et leurs alias. Chaque ligne est un couple <alias de ré-
ponse>=<class de la réponse>.
Par exemple, Il est assez courant de vouloir surcharger la réponse html par défaut (jResponseHtml) en introduisant
une ligne html=myhtmlresponse. Voir plus en détails dans personnalisation de réponse commune
Ci-dessous les valeurs par défaut des différents type de réponses :
[responses]
html = jResponseHtml
redirect = jResponseRedirect
redirectUrl = jResponseRedirectUrl
binary = jResponseBinary
text = jResponseText
jsonrpc = jResponseJsonrpc
json = jResponseJson
xmlrpc = jResponseXmlrpc
xul = jResponseXul
xuloverlay = jResponseXulOverlay
xuldialog = jResponseXulDialog
xulpage = jResponseXulPage
rdf = jResponseRdf
xml = jResponseXml
zip = jResponseZip
rss2.0 = jResponseRss20
atom1.0 = jResponseAtom10
css= jResponseCss
ltx2pdf= jResponseLatexToPdf
tcpdf = jResponseTcpdf

27.3.4 section error_handling

Les paramètres de cette section permettent de configurer les notifications survenant lors de l’exécution d’un script
de l’application. Pour plus de détails, voir la documentation sur la gestion d’erreurs.
Les notifications ont différents niveaux d’importance. Jelix défini les niveaux suivants correspondant à ceux de PHP :
– default = niveau sélectionné si aucun autre niveau ne correspond
– error = signale une erreur nécessitant l’interruption du script
– warning = signale un mauvais traitement sans toutefois névessiter l’interruption du script
– notice = signale une erreur potentielle
– strict = signale des messages de moteur PHP pour améliorer l’interopérabilité et la compatibilité du script
Ci-dessous, l’ensemble des paramètres de la section :
[error_handling]
messageLogFormat = "%date%\t[%code%]\t%msg%\t%file%\t%line%\n"
logFile = error.log
email = root@localhost
emailHeaders = "Content-Type: text/plain; charset=UTF-8\nFrom: webmaster@yoursite. ←-
com\nX-Mailer: Jelix\nX-Priority: 1 (Highest)\n"
Jelix 1.0.6
Guide du développeur
186 / 225

quietMessage="A technical error has occured. Sorry for this trouble."

showInFirebug = off

; mots clés que vous pouvez utiliser : ECHO, ECHOQUIET, EXIT, LOGFILE, SYSLOG, ←-
MAIL, TRACE
default = ECHO EXIT
error = ECHO EXIT
warning = ECHO
notice = ECHO
strict = ECHO
; pour les exceptions, il y a implicitement un EXIT
exception = ECHO

– messageLogFormat et logFile configurent la sortie en fichier de log (LOGFILE ou SYSLOG)


– email et emailHeaders configurent la sortie sous forme de mail (MAIL)
– quietMessage défini un message neutre pour l’utilisateur (ECHOQUIET)
– showInFirebug : si affectée à on, toutes les notifications seront renvoyés vers la console de l’extension Firebug
du navigateur Firefox via son api console.
les dernières options permettent d’associer un format de sortie à chaque niveau de notification.

27.3.5 section compilation

Défini le comportement du moteur de template de Jelix. Et notamment de la phase de compilation. Voir la documen-
tation sur les templates pour plus de détails.
[compilation]
checkCacheFiletime = on
force = off

– checkCacheFiletime : si on alors un template est recompilé si sa date de modification est plus récente que le
fichier PHP résultant de la compilation.
– force : si on, le template est recompilée systématiquement.

27.3.6 section urlengine

@TODO : à compléter

27.3.7 section logfiles

Cette section défini comment seront écrits les logs à l’aide de jLog.
Les fichiers logs sont stockés dans le dossier /var/log/ de votre application. Vous pouvez définir un fichier de log
par module en associant le nom du module à un nom de fichier log et faisant un appel à jLog en passant en dernier
argument le nom du module.
; log par défaut
default = messages.log

; log "news"
news = news.log
Jelix 1.0.6
Guide du développeur
187 / 225

Autre exemple utilisant l’extension Firebug du navigateur Firefox (ce qui permet une vision très rapide des messages
de déboggage).
[logfiles]
default="!firebug"
file = "messages.log"

Et pour un dump de contenu de taille importante, il suffit d’indiquer le type ’file’ au dernier paramètres des méthodes
de jLog pour l’obtenir à nouveau dans un fichier de log classique.
Pour plus de détails sur l’utilisation des fichiers log dans Jelix se reporter au manuel concernant jLog

27.3.8 section mailer

Défini les paramètres d’envoi de mail à travers l’application, comme par exemple pour une authentification ou encore
plus bas-niveau pour les notifications.
[mailer]
webmasterEmail = root@localhost
webmasterName =

; How to send mail : "mail" (mail()), "sendmail" (call sendmail), or "smtp" (send ←-
directly to a smtp)
mailerType = mail
; Sets the hostname to use in Message-Id and Received headers
; and as default HELO string. If empty, the value returned
; by SERVER_NAME is used or ’localhost.localdomain’.
hostname =
sendmailPath = "/usr/sbin/sendmail"

; if mailer = smtp , fill the following parameters

; SMTP hosts. All hosts must be separated by a semicolon : "smtp1.example.com:25; ←-


smtp2.example.com"
smtpHost = "localhost"
; default SMTP server port
smtpPort = 25
; SMTP HELO of the message (Default is hostname)
smtpHelo =
; SMTP authentication
smtpAuth = off
smtpUsername =
smtpPassword =
; SMTP server timeout in seconds
smtpTimeout = 10

27.3.9 section acl

Défini les paramètres de la gestion des droits d’accès dans l’application. Voir la documentation sur la gestion des
droits
[acl]
driver = db
enableAclDbEventListener = off
Jelix 1.0.6
Guide du développeur
188 / 225

27.3.10 section sessions

Défini le mode de gestion des sessions PHP (fichier ou bases de données). Pour plus de détails, voir la documentation
sur les sessions
[sessions]
shared_session = off
; Use alternative storage engines for sessions
;
; usage :
;
; storage = "files"
; files_path = "app:var/sessions/"
;
; or
;
; storage = "dao"
; dao_selector = "jelix~jsession"
; dao_db_profile = ""
Jelix 1.0.6
Guide du développeur
189 / 225

Cinquième partie

Aide au développement
Jelix 1.0.6
Guide du développeur
190 / 225

Les outils fournis dans Jelix pour aider au développement d’une application.
Jelix 1.0.6
Guide du développeur
191 / 225

Chapitre 28

Configurer le gestionnaire d’erreur

Les classes du framework peuvent générer des erreurs de deux façons différentes par :
– un trigger_error (erreur PHP)
– une exception
Une erreur PHP est générée dans le cas d’une erreur technique due à un défaut dans la programmation. C’est alors
au développeur de corriger l’erreur.
Une exception est générée dans le cas d’une erreur qui peut survenir de façon imprévisible durant l’exécution d’une
action. Par exemple une erreur suite à l’impossibilité de se connecter sur une base de données ou alors une erreur
"fonctionnelle", "métier".

28.1 Paramétrage des gestionnaires d’erreurs

Quelle que soit l’origine de l’erreur, celle-ci passe par un gestionnaire d’erreur (sauf les exceptions interceptées par
un try/catch). Il y a un gestionnaire d’erreur attribué aux erreurs PHP et un autre attribué aux exceptions.
Les gestionnaires d’erreurs sont chargés d’effectuer les actions indiquées dans la configuration, selon le type d’erreur.
Il s’agit des paramètres default, error, warning, notice, strict, exception dans la section error_handling. Chacun
de ses paramètres doit contenir un ou plusieurs de ces mots qui indique une action a effectuer :

L’option messageLogFormat indique le formatage du message d’erreur pour son stockage dans le fichier de log,
syslog ou le mail.
Si, pour l’action ECHO avec les réponses HTML et XUL, vous voulez afficher les erreurs dans Firebug (une exten-
sion pour Firefox), mettez l’option showInFirebug à on (jelix 1.0).

28.2 Code erreur

Chaque message d’erreur est localisé dans les fichiers properties et chaque erreur devrait posséder un numéro. Ce
numéro est indiqué dans les fichiers properties des messages localisés, de cette façon :
cle.chaine = (code_erreur)message d’erreur
Le message d’erreur au final ne contiendra pas le code erreur. Et ce dernier sera extrait.
Voici les plages de code erreurs
Si vous générez des erreurs pour vos propres besoins, leurs codes doivent être supérieur à 5000.
Jelix 1.0.6
Guide du développeur
192 / 225
Jelix 1.0.6
Guide du développeur
193 / 225

Chapitre 29

Développer des tests unitaires

29.1 Développer des tests unitaires

Le développement de test unitaires est de plus en plus présents dans les projets, et Jelix propose de quoi en réaliser
facilement. La réalisation des tests unitaires fait d’ailleurs partie des méthodes de développement comme XP (eXtreme
programming). Le processus de développement veut, en théorie (et en gros), qu’à chaque fois que l’on développe une
fonctionnalité, une méthode, on développe aussi les tests qui vont permettre de vérifier le bon fonctionnement de la
méthode. Et à chaque fois que l’on modifie ou ajoute un bout de code, on lance tout les tests unitaires pour vérifier
qu’il n’y a pas de regressions. Cela permet ainsi de garantir un minimum, un fonctionnement robuste de l’application.

29.1.1 Préparation

Les tests unitaires dans Jelix ne peuvent s’effectuer qu’avec l’édition "developer" de Jelix. Celle-ci contient en
effet un module spécifique pour lancer les tests unitaires, junittests, et la bibliothèque SimpleTest. Si vous voulez
absolument lancer les tests unitaires sur un serveur en production avec une édition "optimized" de jelix, vous devez y
copier les répertoires lib/simpletest/ et lib/jelix-modules/junittests de l’édition "developer".
Pour pouvoir lancer les tests, il faut aussi ajouter au début du fichier de configuration de votre application :
enableTests = on

Vous devez mettre à off quand vous passez votre application sur le serveur de production, ou utilisez une édition
"optimized" de jelix (ou encore supprimer le module junittests tout simplement). Cela évite que n’importe qui puisse
lancer les tests unitaires.

29.1.2 Création de tests unitaires

les fichiers de tests

Les tests unitaires, ce sont des scripts qui font des tests sur des classes, des méthodes, des fonctions.
Les tests dans Jelix doivent reposer sur la bibliothèque simpletest : vous devez donc réaliser des classes, qui héritent
de la classe UnitTestCase de simpletest, et vous les placez dans un ou plusieurs fichiers dans les répertoires "tests" de
vos modules.
Ces fichiers seront ensuite appelés par le module junittests quand vous voudrez les exécuter.
Les tests peuvent être lancés soit par l’interface web de junittests, soit par le script en ligne de commande fourni par
junittests. Certains tests doivent parfois s’exécuter uniquement via le web, ou uniquement via la ligne de commande
Jelix 1.0.6
Guide du développeur
194 / 225

(tout dépend de la nature de ces tests). Aussi les noms des fichiers de tests doivent se terminer par un suffixe précis
pour faire savoir à junittests les tests qu’il peut lancer dans tel ou tel contexte :
– .html.php : le test ne pourra être lancé que via l’interface web
– .cli.php : le test ne pourra être lancé que via la ligne de commande
– .html_cli.php : le test peut être lancé indifféremment via le web ou via la ligne de commande.
Le nom qui précède le suffixe importe peu. Sachez toutefois qu’il sert de libellé lors des affichages des tests, et une
transformation est effectué sur ce nom pour un affichage plus lisible :
– les points sont transformés en " : "
– les caractères soulignés "_" sont transformés en espaces.
Par exemple si on nomme le fichier ainsi, "jdao.main_api_with_pdo.html.php", le libellé des tests contenus dans ce
fichier sera "jdao : main api with pdo". Et comme il a le suffixe ".html.php", il ne pourra être lancé que via l’interface
web de junittests.

Création d’un test

Pour créer un test, il faut créer une classe héritant de UnitTestCase ou des autres classes héritières de UnitTestCase
proposées par simpletest, et y écrire des méthodes dont le nom doit commencer par "test". Ces méthodes feront alors
les tests que vous désirez, en utilisant l’API de simpletest. Pour plus de détails sur cette API, lisez la documentation sur
le site de simpletest, en particulier la page sur unittestcase. Notez que dans cette documentation, vous devez ignorer
tout ce qui concerne les "reporters" et les "group tests" : le module junittests s’occupant déjà de tout ça. Vous pouvez
aussi regarder les tests qui sont présents dans le module unittest de l’application testapp disponible en téléchargement.
Voici un exemple de test. Admettons que l’on veuille faire des tests sur une classe "panier" d’un module "shop". On
crée alors un fichier "shop/tests/panier.html.php" et on y place la classe suivante :
class testShopPanier extends UnitTestCase {

function testPanierVide () {
$panier = jClasses::create("shop~panier");
$content = $panier->getProductList();
$this->assertIdentical( $content, array());
}
}

Le nom de la classe "testShopPanier" est totalement libre. Mais il faut faire attention que ce ne soit pas un nom déjà
pris par une autre classe de tests dans d’autres modules. Aussi il est recommandé que le nom contienne le nom du
module ou autre signe distinctif.
On a ici créé une fonction qui teste si, lors de la création d’un panier, celui-ci est bien vide. On instancie donc la
classe panier, on appelle sa méthode getProductList qui devrait nous renvoyer une liste de produits. Et ensuite on teste
si le contenu renvoyé est bien un tableau vide.
Vous pouvez ajouter autant de méthodes de tests que vous voulez dans une même classe de tests, mais aussi de
classes dans un seul fichier. Voici un deuxième exemple :
function testAjoutProduit () {
// creation d’un panier
$panier = jClasses::create("shop~panier");

// creation d’un produit


$product = jClasses::create("shop~product");
$product->label = "DVD coluche";
$product->price = 12.40;

// ajout du produit dans le panier


Jelix 1.0.6
Guide du développeur
195 / 225

$panier->addProduct($product);

$liste = $panier->getProductList();

// test si le panier contient bien un produit


$this->assertTrue( count($liste) == 1);

// test si le produit contenu correspond bien à celui mis


$p = $liste[0];
// verification que c’est un objet product
if($this->assertIsA($p , ’product’)){
$this->assertEqual($p->label , ’DVD coluche’);
$this->assertEqual($p->price , 12.40);
}

// on enleve le produit
$panier->removeProduct(’DVD coluche’);

// on vérifie que le panier est bien vide à nouveau


$content = $panier->getProductList();
$this->assertIdentical( $content, array());

29.2 Lancement des tests

Une fois vos tests réalisés, il faut les lancer avec le module junittests.

29.2.1 Via l’interface web

Le lancement des tests se fait en appelant la page principale du module junittests. Un exemple d’url : http ://tes-
tapp.jelix.org/index.php ?module=junittests . Vous pouvez d’ailleurs vous rendre à cette url précise : vous y verrez
tous les tests unitaires sur Jelix ;-)
N’oubliez pas de mettre dans la configuration le paramètre enableTests = on, sinon vous aurez droit à une erreur 404.
Cette première page présente sur la gauche la liste de tous les tests présents dans votre application, classés par
module. Il suffit de cliquer sur un des tests pour le lancer et voir le résultat. Vous avez des liens aussi pour lancer tous
les tests d’un module, ou tous les tests de votre application (attention cependant, les lancer tous peut être long pour
les grosses applications, et provoquer un "timeout" au niveau du navigateur).
À la fin du lancement des tests, il est affiché le nombre de tests unitaires qui sont passés avec succès, et celui des
tests échoués.
Notez que le module junittests utilise sa propre réponse HTML, et fait appel à une feuille de style tests/design.css
qui doit être placée dans le répertoire www de votre application. Vous en trouverez une dans le répertoire install du
module junittests.

29.2.2 Via la ligne de commande

Le lancement des tests se fait en exécutant un script tests.php se trouvant dans le répertoire scripts de l’applica-
tion Jelix. Vous pouvez utiliser l’application testapp (voir dans "Application de test") pour en voir un exemple.
Voici une liste des différentes commandes disponibles :
Jelix 1.0.6
Guide du développeur
196 / 225

Lister tous les tests

Voir la liste de tous les tests de votre application rangés par modules. Vous devez préciser seulement ici le nom du
controleur car le mot-clé "help" renvoie vers l’aide générale de la ligne de commande de Jelix. Exemple :
php tests.php default:help

Lancer tous les tests de l’application

Exécuter l’ensemble des tests de votre application. Pas besoin ici de paramètre particulier, car exécuter tous les tests
de l’application est l’action par défaut. Exemple :
php tests.php

Lancer tous les tests d’un module

Exécuter l’ensemble des tests d’un module spécifié. Vous devez ici donner le nom de votre module en paramètre.
Exemple pour testapp :
php tests.php module jelix_tests

Lancer un test particulier

Exécuter le test spécifié. Vous devez ici donner le nom du module et le nom du test en paramètre, qui est spécifié
dans la commande help (entre parenthèses). Exemple :
php tests.php single jelix_tests core.jlocale

À la fin du lancement des tests, il est affiché le nombre de tests unitaires qui sont passés avec succès, et celui des
tests échoués.
Notez que si vous n’avez pas le fichier tests.php dans le répertoire scripts, vous pouvez récupérer tous les fichiers
nécessaires (le script et le fichier de configuration) dans le répertoire install du module junittests.
Jelix 1.0.6
Guide du développeur
197 / 225

Chapitre 30

Les aides pour debogguer

30.1 jLog

jLog est une classe qui permet de tracer, ou plus précisément d’écrire des messages ou le contenu de variable dans
un fichier journal. Elle possède pour cela deux méthodes statiques :
– jLog : :log($message) pour écrire un message dans le fichier journal
– jLog : :dump($variable, $message) pour écrire le contenu de la variable dans le fichier journal (il s’agit en fait
d’un var_export)
Le fichier journal par défaut est var/log/messages.log dans votre application.
Vous pouvez avoir plusieurs fichiers journaux. Pour cela, dans la configuration, vous indiquez ces fichiers dans la
section logfile :
[logfiles]
default = messages.log
news = modulenews.log

Vous pouvez alors indiquer le code du fichier journal à utiliser, en paramètre supplémentaire aux méthodes log et
dump :
jLog::log("hello !", "news");
jLog::dump($record, "enregistrement news", "news");

Enfin, il arrive que plusieurs développeurs travaillent sur un même serveur : il y aurait alors dans un même fichier
toutes les traces que chacun aurait mis. Il est possible d’avoir autant de fichier journaux que de développeur, à condi-
tion qu’ils aient une adresse IP différente. Il suffit d’inclure "%ip%" dans le nom du fichier :
[logfiles]
default = "messages_%ip%.log"
news = "%ip%_modulenews.log"

Ainsi, si un développeur a son poste de travail en 192.168.1.2, alors il y aura des fichiers 192.168.1.2_module-
news.log et messages_192.168.1.2.log
Vous pouvez aussi construire les noms des fichiers de log avec la date et l’heure : pour cela, incluez un ou plusieurs
des "tags" suivant dans le nom : %Y% (année), %m% (mois), %d% (jour), %H% (heure).
Si vous voulez afficher les messages de log dans la réponse, ou dans Firebug (une extension pour Firefox), indiquez
respectivement " !response" et " !firebug" comme nom de fichier :
[logfiles]
default = "!response"
news = "!firebug"
Jelix 1.0.6
Guide du développeur
198 / 225

Sixième partie

Les classes utilitaires


Jelix 1.0.6
Guide du développeur
199 / 225

Documentation sur les classes utilitaires fournies dans Jelix.


Jelix 1.0.6
Guide du développeur
200 / 225

Chapitre 31

jFilter : vérification et filtrage de données

jFilter est une classe qui permet de vérifier et valider le contenu de chaîne de caractères : mail, nombre, url etc. Elle
est utilisée entre autre par jForms, mais vous pouvez l’utiliser pour vos propres besoins. Pour bon nombre de ces
méthodes, elle fait appel à l’extension filter de PHP (sauf dans les packages de Jelix déstiné à PHP 5.0 et 5.1).
Pour le moment, voir l’API de réference de jFilter.
Jelix 1.0.6
Guide du développeur
201 / 225

Chapitre 32

jDateTime : manipulation de dates et heures

jDateTime est une classe encapsulant une date, permettant de la convertir dans divers formats, mais aussi de faire
des calculs de dates.
Pour créer un objet jDateTime, on peut
– soit passer les valeurs de la date par le constructeur : l’année, le mois, le jour, l’heure, les minutes et les secondes.
Toutes ces valeurs sont facultatives et doivent être des entiers.
– soit l’instancier sans paramètre et utiliser la méthode now() pour l’initialiser à la date/heure courante.
– soit l’instancier sans paramètre et utiliser la méthode setFromString pour l’initialiser à partir d’une chaîne conte-
nant une date et/ou une heure.

32.1 Initialisation à la date/heure courante

La méthode now() initialise l’objet avec la date/heure actuelle.


Exemple :
$dt = new jDateTime();
$dt->now();

echo "la date est ", $dt->year, ",", $dt->month, ",", $dt->day, ",", $dt->hour, ←-
",", $dt->minute, ",", $dt->second;

32.2 Conversion à partir d’une chaîne

La méthode setFromString prend en argument la chaîne en question et un indicateur de format. Ces indicateurs sont
des valeurs numériques qui sont récupérables via des constantes de classe.
jDateTime reconnait les formats suivants :

Pour les formats LANG_*, jDateTime se base sur ce qui est indiqué dans le fichier de locales "format" situé dans le
module jelix, et correspondant à la langue courante configurée dans Jelix.
Exemple :
Jelix 1.0.6
Guide du développeur
202 / 225

$dt = new jDateTime();

$dt->setFromString("2006-04-10",jDateTime::DB_DFORMAT);

echo "la date est ", $dt->year, ",", $dt->month, ",", $dt->day, ",", $dt->hour, ←-
",", $dt->minute, ",", $dt->second;

Vous aurez remarqué les propriétés qui permettent de connaître chaque élément de la date.
On peut aussi, plutôt que spécifier à chaque fois le format, définir un format par défaut via la propriété defaultFormat.
$dt = new jDateTime();
$dt->defaultFormat = jDateTime::DB_DFORMAT;

$dt->setFromString("2006-04-10");

32.3 Conversion vers une chaîne

Pour convertir une date en chaîne, il y a la méthode toString qui accepte en paramètre facultatif l’identifiant de format
dans lequel on veut l’avoir.
$dt->toString(jDateTime::LANG_DFORMAT);

32.4 Calcul de dates

Avec les méthodes sub() et add(), il est possible d’ajouter ou d’enlever des durées à une date. Ces durées sont à
indiquer via un objet jDateTime.
$dt = new jDateTime();
$dt->setFromString("2006-04-10",jDateTime::DB_DFORMAT);

// on veut retirer deux jours


$date2 = new jDateTime(0,0,2);
$dt->sub($date2);
echo $dt->toString(jDateTime::DB_DFORMAT); // affiche 2006-04-08

// on veut ajouter 27h15 heures


$date2 = new jDateTime(0,0,0,27,15);
$dt->add($date2);
echo $dt->toString(jDateTime::DB_DTFORMAT); // affiche 2006-04-09 03:15:00

Si on veut savoir la durée entre deux dates, on utilise alors la méthode durationTo(), qui renvoi cette durée dans un
objet jDateTime :
$dt = new jDateTime();
$dt->setFromString("2006-04-10",jDateTime::DB_DFORMAT);

$dt2 = new jDateTime();


$dt2->setFromString("2006-04-12",jDateTime::DB_DFORMAT);

// calcul la durée entre $dt jusqu’à $dt2


$dt3 = $dt->durationTo($dt2);
echo $dt3->toString(jDateTime::DB_DTFORMAT); //affiche 0000-00-02 00:00:00
Jelix 1.0.6
Guide du développeur
203 / 225

Attention, les dates doivent être supérieur au 01/01/1970.

32.5 Comparaison de dates

Pour comparer deux dates, il y a la méthode compareTo()


$dt = new jDateTime();
$dt->setFromString("2006-04-10",jDateTime::DB_DFORMAT);

$dt2 = new jDateTime();


$dt2->setFromString("2006-04-12",jDateTime::DB_DFORMAT);

$result = $dt->compareTo($dt2);

compareTo renvoit :
– -1 si $dt < $dt2
– 0 si les deux dates sont égales
– 1 si $dt > $dt2
Jelix 1.0.6
Guide du développeur
204 / 225

Chapitre 33

jMailer : envoi de mails

33.1 Classe jMailer

jMailer est une classe permettant l’envoi d’email depuis un contrôleur.


Quelques fonctionnalités :
– Pièces jointes
– Email HTML
– Destinataires multiples
– Plusieurs méthodes d’envoi
– Support de l’authentification SMTP
jMailer étant basée sur la classe PHPMailer, de nombreux exemples d’utilisation sont disponibles sur internet.

33.1.1 Paramétrage de base

Le paramétrage de base utilisé par jMailer s’effectue dans le fichier var/config/defaultconfig.ini.php de votre appli-
cation dans la section [mailer].

Les différentes options de configuration

– mailerType : méthode utilisée pour envoyer les emails (par défaut smtp)
– mail : utilise la fonction mail de PHP
– sendmail :
– smtp : utilise une connexion directe à un/plusieurs hôte SMTP
– hostname
– sendmailPath
– smtpHost
– smtpPort
– smtpHelo
– smtpAtuh
– smtpUsername
– smtpPassword
– smtpTimeout
Jelix 1.0.6
Guide du développeur
205 / 225

33.2 Envoi d’un email basique

Envoi d’un email texte avec le paramétrage par défaut.


$mail = new jMailer();

$mail->Subject = ’Sujet de l\’email’;


$mail->Body = ’Contenu du message texte’;

$mail->AddAddress(’destinataire@exemple.com’ , ’Nom du destinataire’);

$mail->Send();
Jelix 1.0.6
Guide du développeur
206 / 225

Chapitre 34

jWiki : transformation de texte wiki

jWiki est une classe permettant de transformer un texte wiki dans un autre format, XHTML par exemple. Cette classe
repose sur la classe Wikirenderer version 3.0.
Pour que Wikirenderer puisse réaliser la transformation, il lui faut donner un ensemble d’objets précis, qui ensemble
vont régir "les rêgles de transformation".
Un certain nombre d’ensemble de rêgles sont fournies (voir lib/wikirenderer/rules/), permettant par exemple de
transformer du code wiki wr3 en XHTML. Il est possible d’imaginer des rêgles pour transformer du code dokuwiki
en XHTML, ou encore du code mediawiki en docbook. Toutes les combinaisons sont possibles. Il suffit de fournir ou
développer ces rêgles.
Pour utiliser jWiki, il faut l’instancier en indiquant le nom d’un ensemble de rêgles. Par exemple pour transformer
du code wiki wr3 en XHTML, il y a les rêgles wr3_to_xhtml, on fera donc :
$wr = new jWiki(’wr3_to_xhtml’);
$xhtml = $wr->render($texte_wiki);

Les rêgles par défaut sont dans lib/wikirenderer/rules, mais vous pouvez ajouter les vôtres dans votre application,
par exemple dans votre_appli/plugins/wr_rules/. Bien sûr, il faut déclarer le dépôt de plugins votre_appli/plugins dans
la configuration de Jelix.
Pour plus d’informations sur l’utilisation de jWiki, voir la documentation de Wikirenderer 3.0.
Jelix 1.0.6
Guide du développeur
207 / 225

Chapitre 35

jSession : stockage de sessions

35.1 Classe jSession

jSession permet de stocker les sessions de façon personnalisée, en fonction de paramètres déclarés dans app/var/con-
fig/defaultconfig.ini.php

35.1.1 Nom de la session

Pour diverses raisons, on peut vouloir changer le nom de la session (par défaut, c’est PHPSESSID).
Pour changer ce nom de variable/cookie, on peut utiliser la configuration suivante :
[sessions]
name = "masession"

NB : seuls les caractères alpha-numériques sont autorisés.

35.1.2 Stockage dans un répertoire

Il n’est pas toujours prudent de stocker les sessions dans le répertoire par défaut prévu par l’hébergeur, car celui-ci
peut être accessible de tout le monde, comme /tmp/ par exemple.
Pour utiliser jSession avec un répertoire personnalisé :
[sessions]
storage = "files"
files_path = "app:var/sessions/"

NB : les mots clés app : et lib : sont reconnus.

35.1.3 Stockage dans la base de données

On peut avoir besoin de stocker les données de session en base de données, par exemple pour permettre un partage
aisé en cas de répartition de charge entre plusieurs serveurs web.
Pour utiliser jSession avec un Dao :
Jelix 1.0.6
Guide du développeur
208 / 225

[sessions]
storage = "dao"
dao_selector = "jelix~jsession"
dao_db_profile = ""

NB : un dao est fourni par défaut dans le module jelix, son sélecteur est : jelix~jsession.
La structure de table pour ce DAO est :
CREATE TABLE ‘sessions‘ (
‘id‘ varchar(64) NOT NULL,
‘creation‘ datetime NOT NULL,
‘access‘ datetime NOT NULL,
‘data‘ text NOT NULL,
PRIMARY KEY (‘id‘)
) DEFAULT CHARSET=utf8;
Jelix 1.0.6
Guide du développeur
209 / 225

Septième partie

Les plugins de Jelix


Jelix 1.0.6
Guide du développeur
210 / 225

Documentation de référence sur les plugins fournis avec Jelix


Jelix 1.0.6
Guide du développeur
211 / 225

Chapitre 36

Plugins de template

Toute la liste des plugins de templates fournis avec Jelix.

36.1 Modificateurs

36.1.1 Les modificateurs

Les modificateurs sont des fonctions qui permettent de modifier l’affichage d’une variable de template. Ils ne sont
donc utilisé que lors des instructions d’affichage.

cat

Ce modificateur permet de concaténer une chaîne de caractère à une variable. Exemple :


Soit la variable de template $foo ayant pour valeur ’bar’ :
$rep->body->assign(’foo’, ’bar’);

Utilisation du modificateur cat dans le template. On concatène la chaîne ’toto’ à la variable $foo :
<p>{$foo|cat:’toto’}</p>

Ce qui donnera l’affichage :


<p>bartoto</p>

count_characters

Ce modificateur de template compte le nombre de caractères contenus dans une variable. Exemple :
Soit la variable de template $foo ayant pour valeur ‘bar’ :
$rep->body->assign(’foo’, ’bar’);

Utilisation de count_characters dans le template :


<p>$foo contient {$foo|count_characters} caractères</p>

Ce qui donnera l’affichage :


<p>$foo contient 3 caractères</p>
Jelix 1.0.6
Guide du développeur
212 / 225

count_paragraphs

Ce modificateur de template permet de compter le nombre de paragraphes contenus dans une variable. Exemple :
Prenons la variable $foo contenant le texte suivant et qu’on assigne au template :
$foo = ’Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\n\n
Vivamus ornare, enim bibendum mollis interdum, magna quam tristique lacus, sed ←-
vestibulum urna augue et nisi.’;

$rep->body->assign(’foo’, $foo);

On affiche alors le texte ainsi que le nombre de paragraphes qu’il contient :


<p>{$foo}<br/>Contient : {$foo|count_paragraphs} paragraphes</p>

Ce qui donne :
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Vivamus ornare, enim bibendum mollis interdum, magna quam tristique lacus, sed ←-
vestibulum urna augue et nisi.
Contient : 2 paragraphes</p>

count_sentences

Ce modificateur de template permet de compter le nombre de phrases contenues dans une variable. Exemple :
Prenons la variable $foo contenant le texte suivant et qu’on assigne au template :
$foo = ’Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Vivamus ornare, enim bibendum mollis interdum, magna quam tristique lacus, sed ←-
vestibulum urna augue et nisi.’;
$rep->body->assign(’foo’, $foo);

On affiche alors le texte ainsi que le nombre de phrases qu’il contient :


<p>{$foo}<br/>Contient : {$foo|count_sentences} phrases</p>

Ce qui donne :
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Vivamus ornare, enim bibendum mollis interdum, magna quam tristique lacus, sed ←-
vestibulum urna augue et nisi.
Contient : 2 phrases</p>

count_words

Ce modificateur de template permet de compter le nombre de mots contenus dans une variable. Exemple :
Prenons la variable $foo contenant le texte suivant et qu’on assigne au template :
$foo = ’Lorem ipsum dolor sit amet, consectetuer adipiscing elit.’;
$rep->body->assign(’foo’, $foo);

On affiche alors le texte ainsi que le nombre de mots qu’il contient :


<p>{$foo}<br/>Contient : {$foo|count_words} mots</p>

Ce qui donne :
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Contient : 8 mots</p>
Jelix 1.0.6
Guide du développeur
213 / 225

date_format

escxml

eschtml

indent

Ce modificateur de template indente chaque ligne de texte contenu dans une variable.

Exemple d’utilisation

Prenons la variable $foo contenant le texte suivant et qu’on assigne au template :


$foo = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Vivamus ornare, enim bibendum mollis interdum."
$rep->body->assign(’foo’, $foo);

On affiche alors le texte contenu dans $foo dans le template :


{$foo|indent}

Ce qui donne :

Lorem ipsum dolor sit amet, consectetuer adipiscing elit.


Vivamus ornare, enim bibendum mollis interdum.

Paramètres

Indent accepte 2 paramètres :


– le nombre de caractères à répéter pour l’indentation. Par défaut vaut 4
– le caractère à répéter. Par défaut est un espace.
{$foo|indent:"15"}

Lorem ipsum dolor sit amet, consectetuer adipiscing elit.


Vivamus ornare, enim bibendum mollis interdum.

{$foo|indent:"1":"\t"}

Lorem ipsum dolor sit amet, consectetuer adipiscing elit.


Vivamus ornare, enim bibendum mollis interdum.

36.1.2 jdatetime

Le modificateur jdatetime permet de convertir une chaîne contenant une date avec un certain format, vers une chaîne
d’un autre format. Ce modificateur utilise la classe jDateTime. Par défaut, le modificateur attend une chaine au format
base de données (jDateTime : :BD_DTFORMAT) et renvoi la date au format correspondant à la langue sélectionnée
(jDateTime : :LANG_DTFORMAT).
<p>la date est {$myDate|jdatetime}.</p>
Jelix 1.0.6
Guide du développeur
214 / 225

Si $myDate=’2006-04-12 01 :05 :26’ et si la langue est fr, alors cela affiche


la date est 12/04/2006 01h05mn26s.

Pour indiquer d’autres formats, vous devez indiquer l’une des chaînes en paramètre au modificateur :
Le premier paramètre indique le format de la chaîne que le modificateur reçoit, le deuxième, le format de la chaîne
en résultat.
<p>la date est {$myDate|jdatetime:’db_date’:’timestamp’}.</p>

si $myDate=’2006-04-15’ alors cela affiche


la date est 1145052000.

36.1.3 regexp_replace

36.1.4 replace

36.1.5 spacify

36.1.6 printf

36.1.7 strip

36.1.8 truncate

36.1.9 wordwrap

36.1.10 html :nl2br

36.2 Fonctions diverses

Divers plugins sont de simple fonctions qui affichent quelque chose selon les paramètres.

36.2.1 zone

Permet l’affichage d’une zone.


<div>
{zone ’module~une_zone’}
</div>

C’est en fait l’équivalent de


$tpl->assignZone(’ZONE’,’module~une_zone’);

<div>

{$ZONE}

</div> </code>
Jelix 1.0.6
Guide du développeur
215 / 225

36.2.2 jlocale

36.2.3 jurl

36.2.4 html : pagelinks

Lorsque que l’on doit afficher une liste de résultats à l’écran et que cette liste est longue, il peut être judicieux de
la répartir sur plusieurs pages. Le plugin Pagelinks facilite l’affichage d’un tel système de pagination, avec des liens
pointant vers les différentes pages de résultats.
Pour utiliser le plugin avec les comportements par défaut, il suffit d’utiliser la syntaxe suivante.
{pagelinks module~action, paramètres de l’action, nombre total de résultats, ←-
index résultat courant, nombre de résultats par page, nom du paramètre d’ ←-
offset, propriétés d’affichage}

Exemple :
<p>{pagelinks ’myModule~default_index’, array(), 283, 60, 15, "offset"}</p>

Paramètres

Module~Action

Sélecteur de l’action qui doit être appelé par les liens de pages.

Paramètres de l’action

Tableau contenant les paramètres métiers à placer dans l’url des liens de pages.

array("param1" => 1, "param2" => "deux")

Si il n’y aucun paramètre à passer, on utilise un tableau vide :

array()

Nombre total de résultats

Nombre entier représentant le nombre total des résultats répondant à votre requête. Vous devez donc l’avoir calculé
au préalable.

Index résultat courant

Nombre entier représentant l’offset, c’est à dire l’index du résultat courant. En clair : le numéro d’ordre du premier
enregistrement afficher sur la page. Pour la première page, vous metterez 0. Pour les pages suivantes, il est calculé
automatiquement et est passé dans le paramètre dont vous indiquez le nom dans "nom du paramètre d’offset"

Nombre de résultats par page

Nombre entier représentant le nombre de résultats contenus dans une page de résultats.
– *Important** : le plugin ne s’affichera pas si il n’y a pas au moins 2 pages de résultats disponibles.
Jelix 1.0.6
Guide du développeur
216 / 225

Nom du paramètre d’offset

Chaîne de caractère contenant le nom que doit prendre le paramètre correspondant à l’offset dans l’url des liens de
pages.

Propriétés d’affichage

Tableau contenant les paramètres liés à l’affichage du plugin. Ce paramètre est optionnel. S’il est omis, le plugin
utilise le comportement par défaut, à savoir qu’il affiche l’intégralité des liens avec leur intitulé par défaut.
Il est donc possible de personnaliser l’affichage, en définissant le nombre de liens à afficher ainsi que les intitulés
des liens spéciaux (page suivante, page précédente, etc.). Pour cela on ajoute simplement un tableau de paramètres
supplémentaires comme ci-dessous dans l’appel. <p>{pagelinks ’myModule~default_index’, array(), 283, 60, 15,
"offset", array(’start-label’ => ’début’, ’end-label’ => ’fin’, ’prev-label’ => ’précédent’, ’next-label’ => ’suivant’,
’area-size’ => 5)}</p>
Il est ainsi possible de renseigner une ou plusieurs des valeurs d’index suivantes qui viendront écraser le comporte-
ment défini par défaut.
– start-label : Libellé du lien de la première page de résultats disponible. Si la valeur est une chaine vide, le lien ne
sera pas affiché.
– prev-label : Libellé du lien de la page de résultats précédente. Si la valeur est une chaine vide, le lien ne sera pas
affiché.
– next-label : Libellé du lien de la page de résultats suivante. Si la valeur est une chaine vide, le lien ne sera pas
affiché.
– end-label : Libellé du lien de la dernière page de résultats disponible. Si la valeur est une chaine vide, le lien ne
sera pas affiché.
– area-size : Nombre de liens à afficher avant et après la page courante. Si la valeur est 0, tous les liens seront
affiché.
L’exemple suivant renomme les liens "précédent" et "suivant", et masque les liens de début et de fin. De plus un
maximum de 5 pages sera affiché de part et d’autre de la page courante.
<p>{pagelinks ’myModule~default_index’, array(), 283, 60, 15, "offset", array(’ ←-
start-label’ => ’’, ’end-label’ => ’’, ’prev-label’ => ’précédent’, ’next- ←-
label’ => ’suivant’, ’area-size’ => 5)}</p>

L’exemple suivant renomme les liens "précédent" et "suivant", et utilise le libellé par défaut pour les liens de début
et de fin. De plus l’intégralité des liens sera affichée.
<p>{pagelinks ’myModule~default_index’, array(), 283, 60, 15, "offset", array(’ ←-
prev-label’ => ’précédent’, ’next-label’ => ’suivant’)}</p>

Bien entendu, il est aussi possible de possible d’utiliser un tableau de paramètres déclaré dans le controleur.
$properties = array(’start-label’ => ’’,
’prev-label’ => ’précédent’,
’next-label’ => ’suivant’,
’end-label’ => ’’,
’area-size’ => 5);

$rep->body->assign(’properties’,$properties);

L’appel du template aura donc la forme suivante.


<p>{pagelinks ’myModule~default_index’, array(), 283, 80, 15, "offset", ←-
$properties}</p>
Jelix 1.0.6
Guide du développeur
217 / 225

36.2.5 Localisation des intitulés

Il est possible de localiser les intitulés des liens spéciaux en utilisant jLocale de la façon suivante.
$properties = array(’start-label’ => jLocale::get("bar~foo.pagelinks.start"),
’prev-label’ => jLocale::get("bar~foo.pagelinks.prev"),
’next-label’ => jLocale::get("bar~foo.pagelinks.next"),
’end-label’ => jLocale::get("bar~foo.pagelinks.end"),
’area-size’ => 0);

36.2.6 Mise en forme avec CSS

Le plugin Pagelinks met à disposition les classes CSS suivantes pour permettre de styler les liens de pagination
comme désiré.
– ul.pagelinks : sélecteur css de la liste des pages disponibles
– li.pagelinks-start : sélecteur css du lien vers la première page de résultats
– li.pagelinks-prev : sélecteur css du lien vers la page de résultats précédente
– li.pagelinks-current : sélecteur css de la page de résultats courante
– li.pagelinks-disabled : sélecteur css des pages de résultats désactivées
– li.pagelinks-next : sélecteur css du lien vers la page de résultats suivante
– li.pagelinks-end : sélecteur css du lien vers la dernière page de résultats
Exemple de feuille de style minimaliste pour une utilisation de Pagelinks avec les propriétés d’affichage par
défaut.
ul.pagelinks>li {
display: inline;
}

ul.pagelinks>li:before {
content: ’ | ’;
}

ul.pagelinks>li.pagelinks-start:before {
content: ’’;
}

36.2.7 html : urljsstring

Le plugin de template urljsstring permet de générer une chaîne pour du javascript, qui contient une url généré par le
moteur d’url de Jelix, et qui contient aussi des paramètres dynamiques en javascript. Par exemple, imaginons que l’on
veuille ça en javascript :

"/index.php?module=foo&action=bar&t=1547&param1=" + uneValeur + "&param2=" + (val

On pourrait bien évidement écrire cela directement dans le script javascript. Mais si la forme d’url change ? On est
alors obligé de modifier le template.
urljsstring permet d’éviter cela.
Ce plugin accepte trois paramètres :
1. le sélecteur d’action (ex : "foo~default :bar")
Jelix 1.0.6
Guide du développeur
218 / 225

2. un tableau contenant les paramètres de l’url qui ont une valeur déjà calculée. Clés = noms des paramètres.
Valeurs = valeurs des paramètres
3. un tableau contenant les paramètres qui seront créés dynamiquement par le script javascript. Clés = noms des
paramètres. Valeurs = expressions javascript.
Pour générer une url comme l’exemple ci-dessus, on affichera :
{urljsstring "foo~default:bar" , array(’t’=>1547) , array(’param1’=>’uneValeur ←-
’, ’param2’=>’(val*5)’)}

Astuce : pour plus de lisibilité, vous pouvez bien sûr utiliser des variables de template
{assign $paramjs=array(’param1’=>’uneValeur’, ’param2’=>’(val*5)’)}
{urljsstring $selecteur , $paramstatic , $paramjs}

Note : urljsstring génère les doubles quotes de la chaîne. Donc inutile de les rajouter dans votre script.
// ceci est incorrect
var foo = "{urljsstring $selecteur , $paramstatic , $paramjs}"

// ceci est correct


var foo = {urljsstring $selecteur , $paramstatic , $paramjs}

36.3 Médias

Les plugins pour insérer ou afficher des ressources diverses (images, flash..) dans un template.

36.3.1 html : image

Si vous avez besoin d’afficher une image, une balise image suffit amplement.
Mais si vous devez afficher la même image à plusieurs reprises, dans des formats différents, avec des effets spéciaux
hollywoodiens ou presque, le plugin image et là pour vous.

Utilisation du plugin dans un template

Il faut noter que pour les versions 1.0.x le plugin image cherche les images dans le dossier "myapp/www/data/fi-
chiers/".
Le plugin image est un plugin function. L’utilisation la plus simple se présente ainsi :

{image ’toupie.png’}
Jelix 1.0.6
Guide du développeur
219 / 225

Ceci crée le code html ci-dessous <img src="./data/fichiers/toupie.png" />

Des attributs

On peut ajouter une classe :

{image ’toupie.png’, array(’class’=>’right cadre’)}

On peut également ajouter un id :

{image ’toupie.png’, array(’id’=>’image’)}

Ainsi qu’un texte alternatif :

{image ’toupie.png’, array(’alt’=>’ici l\’image d\’une toupie’)}

les modifications disponibles

On peut si l’on veut ajouter des arguments pour modifier l’image d’origine.

{image ’toupie.png’, array(’width’=>100)}

Cela va générer une image sauvegardéé dans "myapp/www/cache/images/"

Si gd n’est pas présent sur le serveur, le plugin ajoute la largeur/hauteur a l’image d’origine sous forme de style.
Jelix 1.0.6
Guide du développeur
220 / 225

{image ’toupie.png’, array(’width’=>100)}

<img src="toupie.png" style="width :100px ;height :100px ;"/>

Changer la taille

On peut spécifier la largeur, la hauteur s’adaptera automatiquement, même chose pour la hauteur.

{image ’toupie.png’, array(’height’=>50)}


{image ’toupie.png’, array(’width’=>100)}

On peut bien sur utiliser les deux ce qui va déformer l’image.

{image ’toupie.png’, array(’width’=>150, ’height’=>50)}

Pour changer la taille de l’image sans la déformer il suffit de demander.

{image ’toupie.png’, array(’width’=>150, ’height’=>50, ’omo’=>true)}

Faire un zoom

Changer la taille de l’image de manière homothétique permet de recadrer l’image. Une autre façon de recadrer est
de faire un zoom.
– 100 affiche 100% de l’image
– 10 affiche 10% de l’image

{image ’toupie.png’, array(’width’=>100, ’zoom’=>50)}


Jelix 1.0.6
Guide du développeur
221 / 225

Alignement et déplacement

Une fois que l’on a recadré notre image, on peut la déplacer, pour visualiser la zone de l’image que l’on veut.
On peut aligner l’image à gauche,

{image ’toupie.png’, array(’width’=>100, ’zoom’=>60, ’alignh’=>’left’)}

ou à droite,

{image ’toupie.png’, array(’width’=>100, ’zoom’=>60, ’alignh’=>’right’)}

en haut,

{image ’toupie.png’, array(’width’=>100, ’zoom’=>60, ’alignh’=>’top’)}*

ou en bas.

{image ’toupie.png’, array(’width’=>100, ’zoom’=>60, ’alignh’=>’bottom’)}

Changer l’extension et la qualité

On peut également changer l’extension pour par exemple transformer un png en jpeg et ainsi alléger l’image.

{image ’toupie.png’, array(’width’=>100, ’ext’=>’jpg’)}

Le jpeg ne prend pas en charge la transparence, ce qui explique le fond noir. / !\ sur un navigateur qui ne prend pas
en charge la transparence des png (<=ie6), le fond ne sera pas noir mais blanc.
Jelix 1.0.6
Guide du développeur
222 / 225

{image ’toupie.png’, array(’width’=>100, ’ext’=>’jpg’, ’quality’=>5)}

C’est léger !

Changer la couleur du fond

– * seulement à partir de la version 1.0.4 **


On peut donner une couleur de fond aux images en png transparent.

{image ’toupie.png’, array(’width’=>100, ’background’=>’#ff5533’)}

Ex : sur cette image convertie en jpeg.

{image ’toupie.png’, array(’width’=>100, ’ext’=>’jpg’, ’background’=>’#ff5533’)}

Ajouter une ombre portée

– * seulement à partir de la version 1.0.4 **


On peut très simplement ajouter une ombre portée.

{image ’toupie.png’, array(’width’=>100, ’shadow’=>true))}


Jelix 1.0.6
Guide du développeur
223 / 225

Une fois l’ombre affichée on peut la déplacer, en modifiant la distance et l’angle.

{image ’toupie.png’, array(’width’=>100, ’shadow’=>true, ’soffset’=>20))}

{image ’toupie.png’, array(’width’=>100, ’shadow’=>true, ’sangle’=>0))}

On peut modifier la netteté de l’ombre (maximum 11),

{image ’toupie.png’, array(’width’=>100, ’shadow’=>true, ’sblur’=>0))}

l’opacité de l’ombre en %
Jelix 1.0.6
Guide du développeur
224 / 225

{image ’toupie.png’, array(’width’=>100, ’shadow’=>true, ’sopacity’=>100))}

et même la couleur.

{image ’toupie.png’, array(’width’=>100, ’shadow’=>true, ’scolor’=>’#ffff00’))}

36.4 Meta

Les plugins meta permettent en général de modifier des propriétés dans la réponse.

36.4.1 meta_html

36.4.2 meta_xul
Jelix 1.0.6
Guide du développeur
225 / 225

Chapitre 37

Plugins pour le coordinateur

Toute la liste des plugins pour le coordinateur, fournis avec Jelix.