A l’heure où j’entends beaucoup parler d’objet, de framework, de dépendance faible, d’injection de dépendance etc. je me suis posé une question. Admettons que dans mon petit framework sans prétention j’ai envie que mes modules soient complètement indépendants, c’est-à-dire que je puisse les prendre un à un et les utiliser avec un projet complètement différent, hors framework. Zend Framework fait cela. Cependant je me suis demandé comment gérer des exceptions personnalisées dans ce cas ?
En effet, dans mon framework, j’ai créé une classe d’exception qui hérite de Exception et qui rajoute des fonctionnalités comme par exemple une méthode permettant d’afficher le message d’erreur bien formaté en HTML avec un fond rouge et presque un gyrophare sur le dessus. Oui mais voilà, quand dans un de mes modules j’ai besoin d’utiliser une exception et que j’ai à afficher le message en utilisant une méthode personnalisée de mon exception, cela casse complètement l’indépendance de mon module. Je ne peux plus le sortir de son contexte car il dépend désormais de la classe d’exception de mon framework ce qui est contraire à ce que je veux.
J’ai vu que Zend Framework crée une classe d’exception spécifique pour son module héritée de la classe d’exception du framework, ce qui lui rend à peu près son indépendance puisqu’en changeant simplement la classe parent, on peut hériter directement de la classe Exception.
Par exemple pour le module de cache, on trouve cette classe d’exception:
<?php
class Zend_Cache_Exception extends Zend_Exception {}
?>
En changeant la classe parent on rend le module indépendant:
<?php
class Zend_Cache_Exception extends Exception {}
?>
Oui mais voilà, dans ce cas Zend_Exception qui hérite directement de Exception n’apporte rien de nouveau. Aucune nouvelle méthode, aucune fonctionnalité. Or dans mon cas, si j’utilise cette façon de procéder les méthodes personnalisées de ma classes d’exception ne seront plus disponibles lorsque je changerai la classe parent par Exception. Une seule conclusion m’est venue à l’esprit: je ne doit pas utiliser les fonctionnalités spéciales de ma classe d’exception dans mes modules. Dommage, car j’ai besoin d’afficher mes messages d’erreurs comme je le veux…
Et puis je me suis demandé si c’était vraiment le rôle de mon module de stopper l’exécution du programme pour afficher le message d’erreur. Non finalement. Si je prends pour exemple l’extension mysqli de PHP, elle ne bloque pas l’exécution du programme si la connexion à la base ne se fait pas. Elle se contente de fournir des méthodes pour récupérer les erreurs. C’est dans cette direction que je vais aller.
Tout d’abord, voici une structure de classe pour mon module avec un exemple d’exception :
<?php
class MonModule
{
private $_error = NULL;
public function __construct()
{
try {
if (!condition) {
throw new Exception('Message d\'erreur');
}
// Suite du code exécuté
} catch (Exception $e) {
$this->_error = $e->getMessage();
}
}
public function getError()
{
return $this->_error;
}
}
?>
Dans ce code on voir donc que mon module n’affiche pas le message d’erreur. Il se contente de le passer à un membre. Dans mon contrôleur, je vais pouvoir faire entrer ma classe d’exception personnalisée en action:
<?php
try {
$instance = new MonModule();
if ($instance->getError()) {
throw new MyException($instance->getError());
}
} catch (MyException $e) {
$e->methodePerso();
}
?>
Ici on travaille directement sur l’instanciation de la classe MonModule(), du coup la valeur retournée par le constructeur est forcément une instance, mais lors de l’utilisation de cette technique sur les méthodes de la classe, on peut améliorer la chose en retournant false :
<?php
class MonModule
{
private $_error = NULL;
public function maMethode()
{
try {
if (!condition) {
throw new Exception('Message d\'erreur');
}
// Suite du code exécuté
return $this;
} catch (Exception $e) {
$this->_error = $e->getMessage();
return false;
}
}
public function getError()
{
return $this->_error;
}
}
?>
Et dans le contrôleur :
<?php
try {
$instance = new MonModule();
if (!$instance->maMethode()) {
throw new MyException($instance->getError());
}
} catch (MyException $e) {
$e->methodePerso();
}
?>
Je ne sais pas si c’est la méthode idéale, mais au moins je suis sûr de conserver l’indépendance de mes classes et de mes exceptions.
Mots-clefs : classes, dépendance, exceptions, php