IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Voir le flux RSS

Blog de CinéPhil

[Actualité] FramElem : mon framework PHP pas à pas - 4. Gestion de la configuration

Note : 4 votes pour une moyenne de 2,00.
par , 03/07/2019 à 01h20 (4595 Affichages)
Avant propos
Dans l'article précédent, nous avons commencé la construction du routeur, servant à lancer le programme contrôleur qui prendra en charge la demande de l'utilisateur. Mais il faut que ce qui est demandé (la langue dans laquelle le site doit être affiché, le module et l'action souhaités) soit réalisable par l'application web.

Ce sont les premières choses que nous allons inscrire dans le système de gestion de configuration...

1. Les fichiers de configuration
Les langues dans lesquelles le site pourra être affiché, les modules (différentes parties du site) et les actions possibles à faire dans ces modules figureront dans un fichier de configuration. Mais il n'est pas rare que la configuration du vrai site soit différente du site en développement. Il y aura donc généralement au moins deux fichiers de configuration : un principal et un contenant des paramètres spécifiques au mode de configuration de l'application (en développement ou en production).

Pour lire un fichier de configuration, nous allons utiliser la fonction PHP parse_ini_file. Nous allons donc créer pour le moment un fichier simple (clic droit puis New / File) nommé "config.ini" dans le dossier "framelem/application/config". Si vous n'avez pas déjà créé le dossier, c'est le moment !
Code inifile : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
; Paramètres de configuration généraux.
; 
; @filesource 	application/config/config.ini
; @author		Philippe Leménager
; @version		V0.1 - plemenager - 2019-06-30 - Création
;
; Historique :
;

[initialisation]
modeAppli = dev ; Site en développement

[langues]
langues[defaut] = fr

[modules]
modules[] = Accueil ; Module d'accueil dans le site

[actions]
Accueil[] = Accueil ; Affichage de la page d'accueil

Plus tard, nous pourrons ajouter dans un fichier "dev.ini" les paramètres spécifiques au site en développement tels que les paramètres de connexion à la base de données locale, le mode d'authentification de l'utilisateur (LDAP ou base de données), le dossier par défaut pour le téléchargement de fichiers... Idem s'il y a des paramètres spécifiques pour le site en production (serveur de base de données, serveur LDAP, espace de stockage des fichiers téléversés sur le site...). Lors de la copie du site sur le serveur de production, il suffira de modifier le fichier "config.ini" en modifiant la valeur du paramètre modeAppli de "dev" à "prod". Et si vous avez d'autres modes (pré-production, test, validation...), il suffira de créer le fichier de configuration supplémentaire et de donner la bonne valeur au paramètre "modeAppli.

2. Le contrôleur de configuration
Nous allons maintenant créer, dans le dossier "framelem/application/controllers", la classe contrôleur qui gère la configuration du site et qu'on appellera naturellement : "Configuration". Ce sera aussi un singleton car la configuration est potentiellement utile partout, pour toutes les fonctions du site.

Comme vous le verrez en commentaire, j'ai construit ce contrôleur de configuration à partir d'un tutoriel de Baptiste Pesquet.

En plus de l'instance du singleton, les autres attributs seront des tableaux donnant la liste des paramètres, des langues, modules et actions possibles. Ajoutons le mode de configuration de l'application (le paramètre "modeAppli" du fichier de config).

Vous connaissez maintenant la technique : création de la classe, écriture des attributs, complétion des commentaires, écriture du lanceur du singleton (getInstance), génération des getters et setters pour les autres attributs, amélioration du code généré avec le contrôle des valeurs passées aux attributs et voilà ce que ça donne :
Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<?php
namespace application\controllers;
 
/**
 * Singleton de gestion des paramètres de configuration.
 *
 * d'après le tutoriel de Baptiste Pesquet http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc
 *
 * @filesource 	application/controllers/Configuration.php
 * @author 		Philippe Leménager
 * @version 	V0.1 - plemenager - 2019-06-30 - Création
 */
class Configuration
{
	/**
	 * Instance du singleton
	 * @staticvar object
	 */
	private static $instance;
 
	/**
	 * Liste des paramètres de configuration
	 * @staticvar array
	 */
	private static $listeParamsAppli;
 
	/**
	 * Mode de configuration de l'application
	 * @staticvar string
	 */
	private static $modeAppli;
 
	/**
	 * Liste des langues possibles
	 * @var array
	 */
	private $listeLangues;
 
	/**
	 * Liste  des modules existants dans l'application
	 * @var array
	 */
	private $listeModules;
 
	/**
	 * Liste des actions possibles
	 * @var array
	 */
	private $listeActions;
 
	/**
	 * Constructeur lancé par getInstance()
	 * @access private
	 */
	private function __construct()
	{
	}
 
	/**
	 * Destructeur
	 */
	function __destruct()
	{}
 
	/**
	 * Instancie le gestionaire de configuration
	 * @return Configuration
	 */
	public static function getInstance()
	{
		if(is_null(self::$instance))
		{
			self::$instance = new self;
		}
 
		return self::$instance;
	}
 
	/**
	 * Donne tous les paramètres de l'application
	 * @access private
	 * @return array
	 */
	private static function getListeParamsAppli()
	{
		return self::$listeParamsAppli;
	}
 
	/**
	 * Définit les paramètres de l'application
	 * @access private
	 * @param array $listeParamsAppli
	 */
	private static function setListeParamsAppli($listeParamsAppli)
	{
		if(is_array($listeParamsAppli))
		{
			self::$listeParamsAppli = $listeParamsAppli;
		}
	}
 
	/**
	 * Donne le mode de configuration de l'application
	 * @access private
	 * @return string
	 */
	private static function getModeAppli()
	{
		return self::$modeAppli;
	}
 
	/**
	 * Définit le mode de configuration de l'application
	 * @access private
	 * @param string $modeAppli
	 */
	private static function setModeAppli($modeAppli)
	{
		if(is_string($modeAppli))
		{
			self::$modeAppli = $modeAppli;
		}
	}
 
	/**
	 * Donne la liste des langues disponibles pour l'application
	 * @return array
	 */
	public function getListeLangues()
	{
		return $this->listeLangues;
	}
 
	/**
	 * Définit la liste des langues disponibles pour l'application
	 * @access private
	 * @param array $listeLangues
	 */
	private function setListeLangues($listeLangues)
	{
		if(is_array($listeLangues))
		{
			$this->listeLangues = $listeLangues;
		}
	}
 
	/**
	 * Donne la liste des modules disponibles dans l'application
	 * @return array
	 */
	public function getListeModules()
	{
		return $this->listeModules;
	}
 
	/**
	 * Définit la liste des modules disponibles dans l'application
	 * @access private
	 * @param array $listeModules
	 */
	private function setListeModules($listeModules)
	{
		if(is_array($listeModules))
		{
			$this->listeModules = $listeModules;
		}
	}
 
	/**
	 * Donne la liste des actions possibles
	 * @return array
	 */
	public function getListeActions()
	{
		return $this->listeActions;
	}
 
	/**
	 * Définit la liste des actions possibles
	 * @access private
	 * @param array $listeActions
	 */
	public function setListeActions($listeActions)
	{
		$this->listeActions = $listeActions;
	}
}
?>

Complétons maintenant le contrôleur Configuration à la suite du code ci-dessus avec une méthode qui charge un fichier de configuration et le transforme en tableau PHP contenant les paramètres du fichier :
Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
	/**
	 * Charge un fichier de configuration et renvoie son contenu sous forme de tableau de paramètres
	 * @param string $chemin - Le chemin où se trouve le fichier à lire à partir de la racine du site 
	 * @param string $nomFichier - Le nom du fichier de configuration à lire
	 * @throws \ErrorException - Si le fichier n'est pas trouvé
	 * @return array - Le tableau de paramètres lus dans le fichier
	 */
	public function chargeFichierConfig($chemin, $nomFichier)
	{
		if(substr(trim($chemin), -1) != DIRECTORY_SEPARATOR)
		{
			// Si le séparateur final n'est pas présent, on l'ajoute
			$chemin = trim($chemin).DIRECTORY_SEPARATOR;
		}
		else
		{
			$chemin = trim($chemin);
		}
 
		if(is_file(DIR_ROOT.$chemin.trim($nomFichier)))
		{
			// Si le fichier de config existe, on le lit et on le renvoie sous forme de tableau
			return parse_ini_file(DIR_ROOT.$chemin.trim($nomFichier));
		}
		else 
		{
			throw new \ErrorException('Fichier de configuration "'.trim($nomFichier).'" non trouvé dans "'.$chemin.'".');
		}
	} // Fin public function chargeFichierConfig($chemin, $nomFichier)

Maintenant, nous avons besoin de programmer un autre outil (une méthode) qui va lire un paramètre particulier :
Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
	/**
	 * Lit un paramètre de configuration
	 * @param string $nomParametre - Le nom du paramètre à lire
	 * @return mixed|NULL - La valeur du paramètre lu si trouvé
	 */
	public function lireParametre($nomParametre)
	{
		if (isset(self::getListeParamsAppli()[$nomParametre]))
		{
			// Si le paramètre demandé existe, on retourne sa valeur
			return self::getListeParamsAppli()[$nomParametre];
		}
		else
		{
			// Sinon on retourne null
			return null;
		}
	} // Fin public function lireParametre($nomParametre)

Programmons maintenant le constructeur qui va remplir les attributs du Contrôleur en lisant le ou les fichiers de configuration :
Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
	/**
	 * Constructeur lancé par getInstance()
	 * Remplit l'instance du contrôleur avec les paramètres lus dans les fichiers de configuration
	 * @access private
	 */
	private function __construct()
	{
		// Lit le fichier de configuration principal config.ini
		self::setListeParamsAppli(self::chargeFichierConfig('application/config', 'config.ini'));
 
		// Valorise le mode de configuration de l'application
		self::setModeAppli($this->lireParametre('modeAppli'));
 
		if(self::getModeAppli() != 'prod')
		{
			// Si l'application n'est pas en mode de configuration de  production on affiche les erreurs PHP
			ini_set('display_errors', 1);
			error_reporting(E_ALL);
		}
 
		if(is_file(DIR_ROOT.'application/config/'.self::getModeAppli().'ini'))
		{
			// Si le fichier de configuration correspondant au modeAppli existe, on le charge et on complète la liste des paramètres de l'application
			$paramsSupp = $this->chargeFichierConfig('application/config/', self::getModeAppli().'ini');
 
			self::setListeParamsAppli(array_merge(self::getListeParamsAppli(), $paramsSupp));
		}
 
		// Extrait de la liste des paramètres les listes des langues et des modules
		// Nota : la liste des actions sera remplie lors de la vérification de l'existence du module par le routeur
		self::setListeLangues($this->lireParametre('langues'));
		self::setListeModules($this->lireParametre('modules'));
	}

Vous remarquerez que j'ai ajouté un test pour afficher les erreurs PHP si l'application n'est pas en production. Nous pouvons donc supprimer du fichier "index.php" le morceau de code qui faisait le même travail. Voici donc la version 0.3 de index.php :
Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?php
/**
 * Point d'accès unique dans le site.
 *
 * Traite l'URL appelée par l'utilisateur et oriente vers le contrôleur correspondant
 *
 * @filesource	index.php
 * @author		Philippe Leménager
 * @version		V0.3 - 2019-07-03 - plemenager - Suppression de l'affichage provisoire des erreurs PHP.
 */
 
 /* Historique :
  * V0.1 - 2019-06-20 - plemenager - Création
  * V0.2 - 2019-07-02 - plemenager - Ajout du lancement du routeur et affichage provisoire des erreurs PHP.
  */
 
// Ajout d'un slash final au répertoire racine du site
define('DIR_ROOT', __DIR__.DIRECTORY_SEPARATOR);
 
/**
 * Autoloader des classes en suivant les namespaces.
 *
 * Code fourni par rawsrc (https://www.developpez.net/forums/blogs/32058-rawsrc/b5109/autoloader/)
 *
 * @param string $full_class_name : Nom complet de la classe (avec son espace de nom)
 */
$autoloader = function($full_class_name)
{
	// on prépare le terrain : on remplace le séparateur d'espace de nom par le séparateur de répertoires du système
	$name = str_replace('\\', DIRECTORY_SEPARATOR, $full_class_name);
 
	// on construit le chemin complet du fichier à inclure :
	// il faut que l'autoloader soit toujours à la racine du site : tout part de là avec __DIR__
	$path = DIR_ROOT.$name.'.php';
 
	// on vérfie que le fichier existe et on l'inclut
	// sinon on passe la main à un autre autoloader (return false)
	if (is_file($path))
	{
		include $path;
	}
	else
	{
		return false;
	}
};
 
// On enregistre la fonction dans le registre d'autoload
spl_autoload_register($autoloader);
 
/**
 * Lancement du routeur et appel de l'action demandée ou par défaut
 */
use application\controllers\Routeur;
Routeur::getInstance()->appelerAction();
?>

Et voici le code complet de la classe Configuration :
Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
<?php
namespace application\controllers;
 
/**
 * Singleton de gestion des paramètres de configuration.
 *
 * d'après le tutoriel de Baptiste Pesquet http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc
 *
 * @filesource 	application/controllers/Configuration.php
 * @author 		Philippe Leménager
 * @version 	V0.1 - plemenager - 2019-06-30 - Création
 */
class Configuration
{
	/**
	 * Instance du singleton
	 * @staticvar object
	 */
	private static $instance;
 
	/**
	 * Liste des paramètres de configuration
	 * @staticvar array
	 */
	private static $listeParamsAppli;
 
	/**
	 * Mode de configuration de l'application
	 * @staticvar string
	 */
	private static $modeAppli;
 
	/**
	 * Liste des langues possibles
	 * @var array
	 */
	private $listeLangues;
 
	/**
	 * Liste  des modules existants dans l'application
	 * @var array
	 */
	private $listeModules;
 
	/**
	 * Liste des actions possibles
	 * @var array
	 */
	private $listeActions;
 
	/**
	 * Constructeur lancé par getInstance()
	 * Remplit l'instance du contrôleur avec les paramètres lus dans les fichiers de configuration
	 * @access private
	 */
	private function __construct()
	{
		// Lit le fichier de configuration principal config.ini
		self::setListeParamsAppli(self::chargeFichierConfig('application/config', 'config.ini'));
 
		// Valorise le mode de configuration de l'application
		self::setModeAppli($this->lireParametre('modeAppli'));
 
		if(self::getModeAppli() != 'prod')
		{
			// Si l'application n'est pas en mode de configuration de  production on affiche les erreurs PHP
			ini_set('display_errors', 1);
			error_reporting(E_ALL);
		}
 
		if(is_file(DIR_ROOT.'application/config/'.self::getModeAppli().'ini'))
		{
			// Si le fichier de configuration correspondant au modeAppli existe, on le charge et on complète la liste des paramètres de l'application
			$paramsSupp = $this->chargeFichierConfig('application/config/', self::getModeAppli().'ini');
 
			self::setListeParamsAppli(array_merge(self::getListeParamsAppli(), $paramsSupp));
		}
 
		// Extrait de la liste des paramètres les listes des langues et des modules
		// Nota : la liste des actions sera remplie lors de la vérification de l'existence du module par le routeur
		self::setListeLangues($this->lireParametre('langues'));
		self::setListeModules($this->lireParametre('modules'));
	}
 
	/**
	 * Destructeur
	 */
	function __destruct()
	{}
 
	/**
	 * Instancie le gestionaire de configuration
	 * @return Configuration
	 */
	public static function getInstance()
	{
		if(is_null(self::$instance))
		{
			self::$instance = new self;
		}
 
		return self::$instance;
	}
 
	/**
	 * Donne tous les paramètres de l'application
	 * @access private
	 * @return array
	 */
	private static function getListeParamsAppli()
	{
		return self::$listeParamsAppli;
	}
 
	/**
	 * Définit les paramètres de l'application
	 * @access private
	 * @param array $listeParamsAppli
	 */
	private static function setListeParamsAppli($listeParamsAppli)
	{
		if(is_array($listeParamsAppli))
		{
			self::$listeParamsAppli = $listeParamsAppli;
		}
	}
 
	/**
	 * Donne le mode de configuration de l'application
	 * @access private
	 * @return string
	 */
	private static function getModeAppli()
	{
		return self::$modeAppli;
	}
 
	/**
	 * Définit le mode de configuration de l'application
	 * @access private
	 * @param string $modeAppli
	 */
	private static function setModeAppli($modeAppli)
	{
		if(is_string($modeAppli))
		{
			self::$modeAppli = $modeAppli;
		}
	}
 
	/**
	 * Donne la liste des langues disponibles pour l'application
	 * @return array
	 */
	public function getListeLangues()
	{
		return $this->listeLangues;
	}
 
	/**
	 * Définit la liste des langues disponibles pour l'application
	 * @access private
	 * @param array $listeLangues
	 */
	private function setListeLangues($listeLangues)
	{
		if(is_array($listeLangues))
		{
			$this->listeLangues = $listeLangues;
		}
	}
 
	/**
	 * Donne la liste des modules disponibles dans l'application
	 * @return array
	 */
	public function getListeModules()
	{
		return $this->listeModules;
	}
 
	/**
	 * Définit la liste des modules disponibles dans l'application
	 * @access private
	 * @param array $listeModules
	 */
	private function setListeModules($listeModules)
	{
		if(is_array($listeModules))
		{
			$this->listeModules = $listeModules;
		}
	}
 
	/**
	 * Donne la liste des actions possibles
	 * @return array
	 */
	public function getListeActions()
	{
		return $this->listeActions;
	}
 
	/**
	 * Définit la liste des actions possibles
	 * @access private
	 * @param array $listeActions
	 */
	public function setListeActions($listeActions)
	{
		$this->listeActions = $listeActions;
	}
 
	/**
	 * Charge un fichier de configuration et renvoie son contenu sous forme de tableau de paramètres
	 * @param string $chemin - Le chemin où se trouve le fichier à lire à partir de la racine du site
	 * @param string $nomFichier - Le nom du fichier de configuration à lire
	 * @throws \ErrorException - Si le fichier n'est pas trouvé
	 * @return array - Le tableau de paramètres lus dans le fichier
	 */
	public static function chargeFichierConfig($chemin, $nomFichier)
	{
		if(substr(trim($chemin), -1) != DIRECTORY_SEPARATOR)
		{
			// Si le séparateur final n'est pas présent, on l'ajoute
			$chemin = trim($chemin).DIRECTORY_SEPARATOR;
		}
		else
		{
			$chemin = trim($chemin);
		}
 
		if(is_file(DIR_ROOT.$chemin.trim($nomFichier)))
		{
			// Si le fichier de config existe, on le lit et on le renvoie sous forme de tableau
			return parse_ini_file(DIR_ROOT.$chemin.trim($nomFichier));
		}
		else
		{
			throw new \ErrorException('Fichier de configuration "'.trim($nomFichier).'" non trouvé dans "'.$chemin.'".');
		}
	} // Fin public function chargeFichierConfig($chemin, $nomFichier)
 
	/**
	 * Lit un paramètre de configuration
	 * @param string $nomParametre - Le nom du paramètre à lire
	 * @return mixed|NULL - La valeur du paramètre lu si trouvé
	 */
	public function lireParametre($nomParametre)
	{
		if (isset(self::getListeParamsAppli()[$nomParametre]))
		{
			// Si le paramètre demandé existe, on retourne sa valeur
			return self::getListeParamsAppli()[$nomParametre];
		}
		else
		{
			// Sinon on retourne null
			return null;
		}
	} // Fin public function lireParametre($nomParametre)
}
?>

3. Utilisation de la configuration dans le routeur
Dans le routeur, nous pouvons maintenant contrôler si la langue, le module et l'action demandés par le navigateur du visiteur existent vraiment. Retournons donc dans le routeur et créons trois méthodes pour vérifier l'existence de la langue, du module puis de l'action dans le module :
Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
	/**
	 * Dit si la langue demandée est disponible dans l'application
	 * @return boolean
	 */
	private function existeLangue()
	{
		if(in_array($this->getLangue(), Configuration::getInstance()->getListeLangues(), TRUE ))
		{
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
 
	/**
	 * Dit si le module demandé existe dans l'application
	 * @return boolean
	 */
	private function existeModule()
	{
		if(in_array($this->getModule(), Configuration::getInstance()->getListeModules(), TRUE ))
		{
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
 
	/**
	 * Dit si l'action demandée existe pour le module
	 * @return boolean
	 */
	private function existeAction()
	{
		if(in_array($this->getAction(), Configuration::getInstance()->lireParametre($this->getModule()), TRUE ))
		{
			// Si l'action existe pour le module, on remplit la liste des actions possibles de l'objet Configuration
			$listeActions = Configuration::getInstance()->lireParametre($this->getModule());
			Configuration::getInstance()->setListeActions($listeActions);
 
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}

On ne va lancer le controleur de l'action demandée que si celle-ci existe sinon, cela provoquerait une erreur PHP. Donc il faut modifier la méthode appelerAction() du routeur :
Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
	/**
	 * Instancie le contrôleur requis et lance l'action demandée
	 * @throws \ErrorException - Si le module ou l'action n'est pas trouvé
	 */
	public function appelerAction()
	{
		if($this->existeModule() && $this->existeAction())
		{
			// Construction du chemin vers la classe de l'action
			$classeControleur = 'application\\modules\\'.$this->getModule().'\\controllers\\'.$this->getAction();
 
			// Instanciation de la classe contrôleur de l'action
			$controleur = new $classeControleur();
 
			// Appel de la méthode par défaut de toute classe d'action
			$controleur->index();
		}
		else 
		{
			throw new \ErrorException('Le module "'.$this->getModule().'" ou l\'action "'.$this->getAction().'" n\'existe pas dans ce site !');
		}
	}

Voici le code complet de la version 0.2 du routeur :
Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
<?php
namespace application\controllers;
 
/**
 * Routeur des requêtes http vers le bon contrôleur à exécuter.
 *
 * @filesource 	application/controllers/Routeur.php
 * @author 		Philippe Leménager
 * @version 	V0.2 - plemenager - 2019-07-03 - Ajout du contrôle de l'existence de la langue, du module et de l'action demandés
 * 
 * Historique : 
 * V0.1 - plemenager - 2019-06-26 - Création
 */
class Routeur
{
	/**
	 * Instance du singleton Routeur
	 * @staticvar object
	 */
	private static $instance = null;
 
	/**
	 * Langue applicable
	 * @var string
	 */
	private $langue;
 
	/**
	 * Module où se trouve l'action à lancer
	 * @var string
	 */
	private $module;
 
	/**
	 * Action à lancer
	 * @var string
	 */
	private $action;
 
	/**
	 * Paramètre(s) éventuel(s)
	 * @var string
	 */
	private $parametres;
 
	/**
	 * Constructeur lancé par getInstance()
	 * @access private
	 */
	private function __construct()
	{
		// Décomposition de l'URI renvoyée par .htaccess
 
		if(empty($_REQUEST))
		{
			// Si pas de REQUEST => accès direct à la page d'accueil du site
			$this->setLangue('fr'); // Langue par défaut = français
			$this->setModule('Accueil');
			$this->setAction('Accueil');
		}
		else
		{
			// Une REQUEST a été demandée
			$this->setLangue($_REQUEST['langue']);
			$this->setModule($_REQUEST['module']);
			$this->setAction($_REQUEST['action']);
 
			if(isset($_REQUEST['param']))
			{
				$this->setParametres($_REQUEST['param']);
			}
		}
	} // Fin private function __construct()
 
	/**
	 * Destructeur
	 */
	function __destruct()
	{}
 
	/**
	 * Permet l'instanciation du singleton Routeur
	 * @return Routeur
	 */
	public static function getInstance()
	{
		if(is_null(self::$instance))
		{
			// Si le Routeur n'a jamais été instancié, on l'instancie
			self::$instance = new self;
		}
 
		return self::$instance;
	}
	/**
	 * Donne la langue applicable
	 * @return string
	 */
	public function getLangue()
	{
		return $this->langue;
	}
 
	/**
	 * Détermine la langue applicable
	 * @access private
	 * @param string $langue
	 */
	private function setLangue($langue)
	{
		if(is_string($langue) && strlen(trim($langue)) > 1)
		{
			$this->langue = $langue;
		}
	}
 
	/**
	 * Donne le module où se trouve l'action à lancer
	 * @return string
	 */
	public function getModule()
	{
		return $this->module;
	}
 
	/**
	 * Détermine le module où se trouve l'action à lancer
	 * @access private
	 * @param string $module
	 */
	private function setModule($module)
	{
		if(is_string($module) && strlen(trim($module)) > 1)
		{
			$this->module = trim(ucfirst($module));
		}
	}
 
	/**
	 * Donne l'action à lancer
	 * @return string
	 */
	public function getAction()
	{
		return $this->action;
	}
 
	/**
	 * Détermine l'action à lancer
	 * @access private
	 * @param string $action
	 */
	private function setAction($action)
	{
		if(is_string($action) && strlen(trim($action)) > 1)
		{
			$this->action = trim(ucfirst($action));
		}
	}
 
	/**
	 * Donne le(s) paramètre(s) éventuel(s)
	 * @return string
	 */
	public function getParametres()
	{
		return $this->parametres;
	}
 
	/**
	 * Détermine le(s) paramètre(s) éventuel(s)
	 * @access private
	 * @param string $parametres
	 */
	private function setParametres($parametres)
	{
		if(is_string($parametres) && strlen(trim($parametres)) > 1)
		{
			$this->parametres = $parametres;
		}
	}
 
	/**
	 * Instancie le contrôleur requis et lance l'action demandée
	 * @throws \ErrorException - Si le module ou l'action n'est pas trouvé
	 */
	public function appelerAction()
	{
		if($this->existeModule() && $this->existeAction())
		{
			// Construction du chemin vers la classe de l'action
			$classeControleur = 'application\\modules\\'.$this->getModule().'\\controllers\\'.$this->getAction();
 
			// Instanciation de la classe contrôleur de l'action
			$controleur = new $classeControleur();
 
			// Appel de la méthode par défaut de toute classe d'action
			$controleur->index();
		}
		else 
		{
			throw new \ErrorException('Le module "'.$this->getModule().'" ou l\'action "'.$this->getAction().'" n\'existe pas dans ce site !');
		}
	}
 
	/**
	 * Dit si la langue demandée est disponible dans l'application
	 * @return boolean
	 */
	private function existeLangue()
	{
		if(in_array($this->getLangue(), Configuration::getInstance()->getListeLangues(), TRUE ))
		{
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
 
	/**
	 * Dit si le module demandé existe dans l'application
	 * @return boolean
	 */
	private function existeModule()
	{
		if(in_array($this->getModule(), Configuration::getInstance()->getListeModules(), TRUE ))
		{
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
 
	/**
	 * Dit si l'action demandée existe pour le module
	 * @return boolean
	 */
	private function existeAction()
	{
		if(in_array($this->getAction(), Configuration::getInstance()->lireParametre($this->getModule()), TRUE ))
		{
			// Si l'action existe pour le module, on remplit la liste des actions possibles de l'objet Configuration
			$listeActions = Configuration::getInstance()->lireParametre($this->getModule());
			Configuration::getInstance()->setListeActions($listeActions);
 
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
 
}
?>

Testons cela en demandant les URL suivantes dans le navigateur :
  • http://localhost/framelem/fr/Accueil/Accueil => nous obtenons le même écran qu'à la fin de l'article précédent ;
  • http://localhost/framelem/it/Accueil/Accueil (langue : italien) => nous obtenons le même écran qu'à la fin de l'article précédent et le système a corrigé automatiquement la langue puisqu'elle n'existe pas ;
  • http://localhost/framelem/fr/Inscription/Accueil (le module Inscription n'existe pas) =>
    Fatal error: Uncaught exception 'ErrorException' with message 'Le module "Inscription" ou l'action "Accueil" n'existe pas dans ce site !' in /home/philippe/eclipse-workspace/framelem/application/controllers/Routeur.php:202 Stack trace: #0 /home/philippe/eclipse-workspace/framelem/index.php(59): application\controllers\Routeur->appelerAction() #1 {main} thrown in /home/philippe/eclipse-workspace/framelem/application/controllers/Routeur.php on line 202
  • http://localhost/framelem/fr/Accueil/Inscription (l'action Inscription n'existe pas dans le module Accueil) => même erreur que ci-dessus.


Ces messages d'erreur sont bien ceux que nous avons programmés mais avec d'autres informations peu compréhensibles par un utilisateur non informaticien.
De plus, nous voyons ces messages d'erreur parce que nous sommes en mode d'application "dev". Si vous passez le paramètre modeAppli à la valeur "prod" dans le fichier config.ini et que vous refaites les deux derniers tests ci-dessus, vous n'obtiendrez qu'une magnifique... page blanche, peu explicite, au lieu des messages d'erreur.

Il convient donc de mettre en oeuvre un système de gestion des erreurs et exceptions rencontrées lors du déroulement des programmes pour afficher des messages clairs à l'utilisateur. Nous verrons ça plus tard car il faut d'abord s'occuper de prévoir la zone d'affichage des éventuelles erreurs dans la page. Nous allons donc, dans le prochain article, travailler sur la construction des pages...

Envoyer le billet « FramElem : mon framework PHP pas à pas - 4. Gestion de la configuration » dans le blog Viadeo Envoyer le billet « FramElem : mon framework PHP pas à pas - 4. Gestion de la configuration » dans le blog Twitter Envoyer le billet « FramElem : mon framework PHP pas à pas - 4. Gestion de la configuration » dans le blog Google Envoyer le billet « FramElem : mon framework PHP pas à pas - 4. Gestion de la configuration » dans le blog Facebook Envoyer le billet « FramElem : mon framework PHP pas à pas - 4. Gestion de la configuration » dans le blog Digg Envoyer le billet « FramElem : mon framework PHP pas à pas - 4. Gestion de la configuration » dans le blog Delicious Envoyer le billet « FramElem : mon framework PHP pas à pas - 4. Gestion de la configuration » dans le blog MySpace Envoyer le billet « FramElem : mon framework PHP pas à pas - 4. Gestion de la configuration » dans le blog Yahoo

Mis à jour 07/10/2019 à 19h50 par CinePhil

Catégories
PHP , Développement Web , PHP

Commentaires

  1. Avatar de xBlackEagle13
    • |
    • permalink
    Merci pour ces excellents tutos.
    Hâte de lire la suite
  2. Avatar de Marco20
    • |
    • permalink
    La démarche de vulgarisation est intéressante, j'ai hâte de lire la suite.
    Merci à toi CinePhil
  3. Avatar de Cryde
    • |
    • permalink
    Pourquoi ne pas utiliser les PSR ? :/
  4. Avatar de sboucher
    • |
    • permalink
    Merci pour ces excellents tutos.
    Savez-vous quand vous allez publier la suite ?