Les énumérations (enum) en php

Les énumérations (enum) en php

Solution 1 : la liste de constantes

Cette solution est valable à partir de la version 4 de php.

L'énumération est un mécanisme de synonymie entre un ensemble de valeurs constantes et un ensemble de noms de variables d'un même espace de noms.

Le mécanisme de synonymie le plus classique est celui de la constante. Les langages qui acceptent ce mécanisme permettent de déclarer et d'utiliser un nom, généralement en visibilité globale, à la place d'une valeur scalaire qui ne sera pas modifiée au cours du temps d'exécution d'un programme.

En php, on écrira :

define ("maConstante" , 5.5);

et pour faire un test de valeur, on écrira quelque chose comme :

if ($maVariable === maConstante)
faireAvec();
else
faireAutrement();

Les constantes sont le moyen le plus simple de simuler une énumération. Mais aussi le moins puissant.

Par exemple, si on doit manipuler une liste de noms de systèmes d'exploitation, on pourrait déclarer :

define ("Linux" , 0);
define ("Mac" , 1);
define ("Windows" , 2);

Ainsi lorsqu'on veut faire un test de valeur sur une variable de ce type, on écrira :

switch ($maVariable) {
 case Linux : 
    faireAvecLinux(); 
    break;
 case Mac : 
    faireAvecMac(); 
    break;
 case Windows : 
    faireAvecWindows(); 
    break;
}

Ce qui est plus lisible que :

switch ($maVariable) {
 case 0 : 
    faireAvecLinux(); 
    break;
 case 1 :
    faireAvecMac(); 
    break;
 case 2 : 
    faireAvecWindows(); 
    break;
}

Cette solution ravira les plus désoeuvrés, mais ne contentera pas les plus exigeants. En effet, dans une liste de constantes, les noms ne sont pas reliés ensemble au sein d'un même groupe et peuvent même être déclarés séparément dans le code source. Ils sont juste placés côte à côte par commodité.

Maintenant lorsqu'on a un ensemble de valeurs constantes qui ont une signification commune, il est plus commode de les regrouper dans un même espace de noms qui ont un sens du point de vue de la lisibilité du programme.

Solution 2 : les clés d'un tableau associatif

Cette solution est valable à partir de la version 4 de php.

La grande force des tableaux en php, c'est que derrière chaque tableau se cache un tableau associatif. Le tableau traditionnel associe des entiers consécutifs à des valeurs d'un certain type, le tableau associatif associe des valeurs d'un type arbitraire à des valeurs d'un autre type. C'est une forme de généralisation de la notion de tableau.

En général, on déclare un tableau associatif de cette manière :

<?php
$array = array( 1, 1, 1, 1,  1, 8=>1,  4=>1, 19, 3=>13);
print_r($array);
?>

L'exemple ci-dessus va afficher :

Array
(
[0] => 1
[1] => 1
[2] => 1
[3] => 13
[4] => 1
[8] => 1
[9] => 19
)

Pour créer une énumération, on procèdera ainsi :

$OS = array ("Linux"=>0, "Mac"=>1, "Windows"=>3);

Et pour faire un test de valeur, on écrira :

switch ($maVariable) {
 case $OS["Linux"] : 
    faireAvecLinux(); 
    break;
 case $OS["Mac"] : 
    faireAvecMac(); 
    break;
 case $OS["Windows"] : 
    faireAvecWindows(); 
    break;
}

On fait ici une utilisation moins courante du tableau d'association, puisqu'on utilise les chaînes de caractères comme clés de recherche dans le tableau et les indices comme valeurs du tableau. Mais cette forme de langage permet de préciser deux choses :

  • les valeurs possibles de maVariable sont remplacées par des expressions claires qui exprime ce que la variable contient ("Linux", "MasOS" et "Windows" est bien plus clair que 0, 1 et 2). Ce qui augmente la lisibilité d'un programme.
  • les valeurs possibles de maVariable sont restreintes à un espace de noms clairement défini (celui des systèmes d'exploitation pour cet exemple). Ce qui augmente encore plus la lisibilité et la compréhension d'un programme.

Noter que la version courte, bien que tentante, ne fonctionnera pas :

$OS = array ("Linux", "Mac", "Windows");

Puisque le préprocesseur php attribuera automatiquement les indices, c'est l'équivalent de :

$OS = array (0=>"Linux", 1=>"Mac", 2=>"Windows");

Hors l'astuce utilisée ici se sert de la clé d'association comme élément de langage.

Solution 3 : Les énumérations statiques de classes

Cette solution n'est utilisable qu'à partir de la version 5 de php.

La classe est une unité de programmation qui représente un concept manipulé par le programme. Il est commode de disposer d'énumérations relatives à une classe ou un concept. Ce qui permet de rendre toujours plus lisible et compréhensible un programme.
Cette solution n'en est pas vraiment une, mais plutôt une extension de la solution précédente, à la programmation objet.

Avec la version 4 de php qui inclut la première, les concepts de programmation objet, on pourrait déclarer le tableau $OS dans une classe conteneur, mais il en deviendrait membre et serait répliqué inutilement avec toutes les instances de la classe conteneur. Ce n'est qu'avec la version 5 de php, qui intègre la notion de membre de classe statique, que l'astuce suivante pourra être utilisée.

Par exemple, si le programme opère des transactions avec le système sur lequel il est installé, on pourra créer une classe System :

class System {

 public static $OS = array("Linux"=>0, "Mac"=>1, "Windows"=>3);
 public static $LinuxFamily = array("debian"=>0, "suze"=>1, "ubuntu"=>3);

 private $name;
 private $family;
 private $version;

 /* Constructeur */
 public __construct($name, $family, $version) {
  $this->name = $name;
  $this-> family = $family;
  $this->version = $version;
 }

 /* Accesseur */
 public function getName() { return $this->name; }
 ...
}

et pour déclarer une variable du type System, on écrira :

$monSysteme = new System(System::$OS["Linux"], System::$LinuxFamily["ubuntu"], "7.10");

Ce qui est forcément plus lisible que :

$monSysteme = new System(0, 3, "7.10");

De la même manière, pour faire un test de valeur, on écrira :

switch ($monSysteme->getName()) {
 case System::$OS["Linux"] : 
    faireAvecLinux(); 
    break;
 case System::$OS["Mac"] : 
    faireAvecMac(); 
    break;
 case System::$OS["Windows"] : 
    faireAvecWindows(); 
    break;
}

Conclusion

Ce document vous a présenté trois techniques qui permettent de pallier à l'absence de la notion d'énumération dans le langage php. Elle ne sont pas très élégantes, mais elles permettent au moins d'apporter plus de lisibilité au code.

Quelques faiblesses de ces techniques :

  • Lourdeur d'écriture : comme le php ne dispose des mécanismes propres aux énumérations (nommage, raccourci de langage...), il est nécessaire de faire quelques abus de langage (utilisation inverse des tableaux d'association) pour utiliser la simulation.
  • Aucun contrôle de type (appartenance de la valeur d'une variable à l'espace de valeurs défini par l'énumération) ne peut être réalisé sur les variables manipulant ces énumérations, à moins de contorsion de langage périlleuses qui auront tendance à obscurcir le code.

Il s'agit juste de solutions temporaires, en attendant que les développeurs de php intègrent enfin cette notion au langage...
Il faut savoir être patient, le langage java n'intègre cette notion que depuis la version 5 (mais avec brio puisque la notion d'énumération est complètement intégrée à la notion de classe).

Ce document intitulé « Les énumérations (enum) en php » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous