par , 03/07/2019 à 02h20 (4875 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 !
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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...