1318 votes

Enumérations en PHP

Je sais que PHP n'a pas encore d'énumérations natives. Mais je me suis habitué à elles dans le monde Java. J'aimerais utiliser les énumérations comme un moyen de donner des valeurs prédéfinies que les fonctions d'autocomplétion des IDE pourraient comprendre.

Les constantes font l'affaire, mais il y a le problème de la collision entre les espaces de noms et (ou en fait parce que ) ils sont globaux. Les tableaux n'ont pas le problème des espaces de noms, mais ils sont trop vagues, ils peuvent être écrasés à l'exécution et les IDE savent rarement comment remplir automatiquement leurs clés sans annotations d'analyse statique ou attributs supplémentaires.

Y a-t-il des solutions ou des solutions de contournement que vous utilisez couramment ? Est-ce que quelqu'un se souvient si les gars de PHP ont eu des idées ou des décisions concernant les énumérations ?

0 votes

1 votes

J'ai créé une fonction de contournement qui énumère les constantes comme bitwise ou non. Je n'ai pas remarqué que vous aviez déjà posé cette question, mais j'ai une meilleure solution que les variables de classe ici : stackoverflow.com/questions/3836385/

0 votes

1651voto

Brian Cline Points 8904

En fonction du cas d'utilisation, j'utiliserais normalement quelque chose comme simple comme les suivantes :

abstract class DaysOfWeek
{
    const Sunday = 0;
    const Monday = 1;
    // etc.
}

$today = DaysOfWeek::Sunday;

Cependant, d'autres cas d'utilisation peuvent nécessiter une plus grande validation des constantes et des valeurs. D'après les commentaires ci-dessous sur la réflexion quelques autres notes Dans ce contexte, voici un exemple élargi qui pourrait mieux convenir à un éventail beaucoup plus large de cas :

abstract class BasicEnum {
    private static $constCacheArray = NULL;

    private static function getConstants() {
        if (self::$constCacheArray == NULL) {
            self::$constCacheArray = [];
        }
        $calledClass = get_called_class();
        if (!array_key_exists($calledClass, self::$constCacheArray)) {
            $reflect = new ReflectionClass($calledClass);
            self::$constCacheArray[$calledClass] = $reflect->getConstants();
        }
        return self::$constCacheArray[$calledClass];
    }

    public static function isValidName($name, $strict = false) {
        $constants = self::getConstants();

        if ($strict) {
            return array_key_exists($name, $constants);
        }

        $keys = array_map('strtolower', array_keys($constants));
        return in_array(strtolower($name), $keys);
    }

    public static function isValidValue($value, $strict = true) {
        $values = array_values(self::getConstants());
        return in_array($value, $values, $strict);
    }
}

En créant une simple classe d'enum qui étend BasicEnum, vous avez maintenant la possibilité d'utiliser les méthodes ainsi pour une simple validation des entrées :

abstract class DaysOfWeek extends BasicEnum {
    const Sunday = 0;
    const Monday = 1;
    const Tuesday = 2;
    const Wednesday = 3;
    const Thursday = 4;
    const Friday = 5;
    const Saturday = 6;
}

DaysOfWeek::isValidName('Humpday');                  // false
DaysOfWeek::isValidName('Monday');                   // true
DaysOfWeek::isValidName('monday');                   // true
DaysOfWeek::isValidName('monday', $strict = true);   // false
DaysOfWeek::isValidName(0);                          // false

DaysOfWeek::isValidValue(0);                         // true
DaysOfWeek::isValidValue(5);                         // true
DaysOfWeek::isValidValue(7);                         // false
DaysOfWeek::isValidValue('Friday');                  // false

D'ailleurs, chaque fois que j'utilise la réflexion au moins une fois. sur une classe statique/const où les données ne changeront pas. (comme dans une énumération), je mets en cache les résultats de ces appels de réflexion, car l'utilisation de nouveaux objets de réflexion à chaque fois aura éventuellement un impact notable sur les performances (stocké dans un tableau assocciatif pour les énumérations multiples).

Maintenant que la plupart des gens ont enfin mis à jour vers au moins 5.3, et SplEnum est disponible, c'est certainement une option viable aussi - tant que vous n'êtes pas gêné par la notion traditionnellement peu intuitive d'avoir un enum réel. instanciations dans l'ensemble de votre base de code. Dans l'exemple ci-dessus, BasicEnum y DaysOfWeek ne peuvent pas être instanciés du tout, et ne devraient pas l'être.

72 votes

Je l'utilise aussi. Vous pouvez également envisager de faire de la classe abstract y final Il ne peut donc pas être instancié ou étendu.

23 votes

Vous pouvez créer une classe à la fois abstract y final ? Je sais qu'en Java, ce n'est pas autorisé. Vous pouvez le faire en php ?

23 votes

@ryeguy Il semble que vous ne pouvez pas le faire. les deux abstract y final . Dans ce cas, j'opterais pour l'abstrait.

189voto

markus Points 22871

Il existe également une extension native. Le site SplEnum

SplEnum donne la possibilité d'émuler et de créer des objets d'énumération nativement en PHP.

http://www.php.net/manual/en/class.splenum.php

Attention :

https://www.php.net/manual/en/spl-types.installation.php

L'extension PECL n'est pas fournie avec PHP.

Une DLL pour cette extension PECL n'est actuellement pas disponible.

5 votes

Voici un exemple avec splenum : dreamincode.net/forums/topic/201638-enum-in-php

4 votes

J'ai fait marche arrière, je préfère quand je peux voir le lien. Cela me donne des informations contextuelles.

1 votes

SplEnum donne la possibilité d'émuler et de créer des objets d'énumération nativement en PHP.

49voto

Peter Bailey Points 62125

Qu'en est-il des constantes de classe ?

<?php

class YourClass
{
    const SOME_CONSTANT = 1;

    public function echoConstant()
    {
        echo self::SOME_CONSTANT;
    }
}

echo YourClass::SOME_CONSTANT;

$c = new YourClass;
$c->echoConstant();

0 votes

Je préfère cette approche simple

3 votes

echoConstant peut être remplacé par __toString . Et puis simplement echo $c

26voto

Andi T Points 464

Yo uso interface au lieu de class :

interface DaysOfWeek
{
    const Sunday = 0;
    const Monday = 1;
    // etc.
}

var $today = DaysOfWeek::Sunday;

6 votes

class Foo implements DaysOfWeek { } et ensuite Foo::Sunday ... quoi ?

3 votes

L'auteur de la question demande une solution pour deux choses : l'espace de noms et l'autocomplétion par les IDE. Comme l'a suggéré la réponse la mieux notée, le moyen le plus simple est d'utiliser la commande class (ou interface ce qui n'est qu'une question de préférence).

6 votes

Les interfaces sont utilisées pour faire respecter l'intégrité de l'implémentation des classes, ce qui est en dehors de la portée d'une interface.

24voto

aelg Points 149

Eh bien, pour un simple java comme enum en php, j'utilise :

class SomeTypeName {
    private static $enum = array(1 => "Read", 2 => "Write");

    public function toOrdinal($name) {
        return array_search($name, self::$enum);
    }

    public function toString($ordinal) {
        return self::$enum[$ordinal];
    }
}

Et de l'appeler :

SomeTypeName::toOrdinal("Read");
SomeTypeName::toString(1);

Mais je suis un débutant en PHP et j'ai du mal avec la syntaxe, donc ce n'est peut-être pas la meilleure solution. J'ai fait quelques expériences avec les constantes de classe, en utilisant Reflection pour obtenir le nom de la constante à partir de sa valeur, ce qui pourrait être plus propre.

0 votes

Bonne réponse, la plupart des autres réponses utilisent des classes. Cependant, vous ne pouvez pas avoir de classes imbriquées.

0 votes

Cela a l'avantage de pouvoir itérer à travers les valeurs avec foreach. Et l'inconvénient qu'une valeur illégale n'est pas détectée.

2 votes

Mais il n'y a pas de complétion automatique dans l'IDE, ce qui stimulerait le travail de devinette. Les constantes permettraient la complétion automatique, ce qui semble mieux.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X