Je sais que PHP n'a pas d'énumérations natives. Mais je m'y suis habitué du monde Java. J'adorerais utiliser les énumérations comme un moyen de donner des valeurs prédéfinies que les fonctionnalités de complétion automatique des IDE pourraient comprendre.
Les constantes font l'affaire, mais il y a le problème de collision de l'espace de noms et (ou en fait parce qu'elles) sont globales. Les tableaux n'ont pas le problème d'espace de noms, mais ils sont trop vagues, ils peuvent être écrasés lors de l'exécution et les IDE savent rarement (jamais?) Comment remplir automatiquement leurs clés.
Y a-t-il des solutions / solutions de contournement que vous utilisez couramment? Est-ce que quelqu'un se souvient si les gars de PHP ont eu des pensées ou des décisions concernant les énumérations?
la source
Réponses:
Selon le cas d'utilisation, j'utiliserais normalement quelque chose de simple comme le suivant:
Cependant, d'autres cas d'utilisation peuvent nécessiter plus de validation des constantes et des valeurs. Sur la base des commentaires ci-dessous sur la réflexion, et quelques autres notes , voici un exemple étendu qui pourrait mieux servir un éventail beaucoup plus large de cas:
En créant une classe d'énumération simple qui étend BasicEnum, vous avez désormais la possibilité d'utiliser des méthodes pour une validation d'entrée simple:
En remarque, 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 en utilisant à chaque fois de nouveaux objets de réflexion aura éventuellement un impact notable sur les performances (stocké dans un tableau associatif pour plusieurs énumérations).
Maintenant que la plupart des gens sont enfin passés à au moins 5.3 et
SplEnum
sont disponibles, c'est certainement une option viable également - tant que cela ne vous dérange pas la notion traditionnellement peu intuitive d'avoir des instanciations d' énumération réelles dans votre base de code. Dans l'exemple ci-dessus,BasicEnum
etDaysOfWeek
ne peuvent pas du tout être instanciés, ni ne devraient l'être.la source
abstract
etfinal
, donc elle ne peut pas être instanciée ou étendue.abstract
etfinal
? Je sais qu'en Java, ce n'est pas autorisé. Vous pouvez le faire en php?abstract
etfinal
. Dans ce cas, je choisirais l'abstrait.null
et amis dans uneswitch
déclaration. Été là.Il existe également une extension native. Le SplEnum
http://www.php.net/manual/en/class.splenum.php
Attention:
https://www.php.net/manual/en/spl-types.installation.php
la source
Et les constantes de classe?
la source
echoConstant
peut être remplacé par__toString
. Et puis simplementecho $c
La meilleure réponse ci-dessus est fantastique. Cependant, si vous
extend
le faites de deux manières différentes, quelle que soit l'extension effectuée en premier, un appel aux fonctions créera le cache. Ce cache sera ensuite utilisé par tous les appels suivants, quelle que soit l'extension par laquelle les appels sont lancés ...Pour résoudre ce problème, remplacez la variable et la première fonction par:
la source
J'ai utilisé des classes avec des constantes:
la source
J'utilise à la
interface
place declass
:la source
class Foo implements DaysOfWeek { }
et puisFoo::Sunday
... quoi?class
(ouinterface
, ce qui n'est qu'une question de préférence).J'ai commenté certaines des autres réponses ici, alors je me suis dit que j'allais aussi peser. En fin de compte, étant donné que PHP ne prend pas en charge les énumérations typées, vous pouvez suivre l'une des deux méthodes suivantes: pirater les énumérations typées ou vivre avec le fait qu'elles sont extrêmement difficiles à pirater efficacement.
Je préfère vivre avec le fait et utiliser à la place le
const
méthode que d'autres réponses ont utilisée ici d'une manière ou d'une autre:Un exemple d'énumération:
En utilisant
Enum
comme une classe de base à partir de laquelle toutes les autres énumérations étendent permet des méthodes d'aide, tels quetoArray
,isValid
et ainsi de suite. Pour moi, les énumérations tapées ( et la gestion de leurs instances ) se retrouvent trop compliquées.Hypothétique
Si , il existait une
__getStatic
méthode magique ( et de préférence aussi une__equals
méthode magique ), une grande partie de cela pourrait être atténuée avec une sorte de modèle multiton.( Ce qui suit est hypothétique; cela ne fonctionnera pas , mais peut-être qu'un jour ça le sera )
la source
Eh bien, pour un simple java comme enum en php, j'utilise:
Et pour l'appeler:
Mais je suis un débutant PHP, aux prises avec la syntaxe, donc ce n'est peut-être pas la meilleure façon. J'en ai expérimenté quelques-unes avec les constantes de classe, en utilisant la réflexion pour obtenir le nom de la constante à partir de sa valeur, peut-être plus propre.
la source
Quatre ans plus tard, je suis tombé à nouveau sur ce sujet. Mon approche actuelle est la suivante, car elle permet l'achèvement du code dans l'IDE ainsi que la sécurité des types:
Classe de base:
Exemple d'énumération:
Exemple d'utilisation:
Notez que toutes les instances de la même entrée d'énumération sont identiques:
Vous pouvez également l'utiliser dans une instruction switch:
Vous pouvez également créer une entrée d'énumération par nom ou valeur:
Ou vous pouvez simplement obtenir le nom (c'est-à-dire le nom de la fonction) à partir d'une entrée d'énumération existante:
la source
const Monday = DaysOfWeek('Monday');
J'ai trouvé cette bibliothèque sur github et je pense qu'elle fournit une alternative très décente aux réponses ici.
Implémentation de PHP Enum inspirée de SplEnum
function setAction(Action $action) {
format
,parse
...)final
pour l'empêcher)Déclaration
Usage
valeurs d'énumération type-hint:
la source
enum
soit ajouté en PHP 7.x) car elle permet l'indication de type.__toString()
cela permet d'indiquer le type, mais en raison de la magie, cela vous permet de faire ce que vous voulez généralement avec les énumérations - utilisez-les dans une instructionswitch
orif
, en comparant directement avec les valeurs des consts. IMO est la meilleure approche en dehors du support de l'énumération native.Si vous devez utiliser des énumérations globalement uniques (c'est-à-dire même lorsque vous comparez des éléments entre des énumérations différentes) et faciles à utiliser, n'hésitez pas à utiliser le code suivant. J'ai également ajouté quelques méthodes que je trouve utiles. Vous trouverez des exemples dans les commentaires tout en haut du code.
la source
eval()
juste pour que vous pouvez déclarer de nouvelles énumérations exécution? Eek. Je ne le sens pas. Comment empêchez-vous d'autres classes de créer une classe Enum incorrecte avant de définir la bonne? Les Enums ne sont-ils pas connus avant l'exécution? Et comme @corsiKa l'a laissé entendre, aucune autocomplétion IDE. Le seul avantage que je vois est le codage paresseux.J'aime aussi les énumérations de Java et pour cette raison, j'écris mes énumérations de cette manière, je pense que c'est le comportement le plus similaire à celui de Java, bien sûr, si certains veulent utiliser plus de méthodes de Java, écrivez-le ici, ou dans classe abstraite mais l'idée principale est intégrée dans le code ci-dessous
la source
FruitsEnum::Apple()
plusFruitsEnum::$Apple
, mais la raison la plus importante est d'empêcher quiconque de cadre$APPLE
, brisant ainsi le ENUM pour toute l'application. L'autre est un simple indicateur statique privé$initialized
qui garantit que l'appelinit()
devient non-op après l'avoir appelé pour la première fois (donc personne ne peut jouer avec ça non plus)..init()
est bizarre, et ça ne me dérange pas l'approche getter.la source
Cela pourrait être aussi simple que
A l'avenir.
PHP RFC: types énumérés
la source
La solution la plus courante que j'ai vue pour les énumérations en PHP a été de créer une classe d'énumération générique, puis de l'étendre. Vous pouvez jeter un oeil à ce .
MISE À JOUR: Alternativement, j'ai trouvé cela sur phpclasses.org.
la source
Voici une bibliothèque github pour gérer les énumérations de type sécurisé en php:
Cette bibliothèque gère la génération de classes, la mise en cache des classes et implémente le modèle de conception Type Safe Enumeration, avec plusieurs méthodes d'assistance pour traiter les énumérations, comme la récupération d'un ordinal pour le tri des énumérations ou la récupération d'une valeur binaire, pour les combinaisons d'énumérations.
Le code généré utilise un ancien fichier de modèle PHP simple, qui est également configurable, afin que vous puissiez fournir votre propre modèle.
C'est un test complet recouvert de phpunit.
php-enums sur github (n'hésitez pas à bifurquer)
Utilisation: (@see usage.php, ou tests unitaires pour plus de détails)
Production:
la source
J'ai pris l'habitude d'utiliser l'approche ci-dessous car elle me donne la possibilité d'avoir une sécurité de type pour les paramètres de fonction, une saisie automatique dans NetBeans et de bonnes performances. La seule chose que je n'aime pas trop, c'est que vous devez appeler
[extended class name]::enumerate();
après avoir défini la classe.la source
DaysOfWeek::$MONDAY = 3;
[extended class name]::enumerate();
après la définition, pourquoi ne le faites-vous pas dans la construction?Ma définition de classe Enum ci-dessous est fortement typée et très naturelle à utiliser et à définir.
Définition:
Basculer sur Enum
Passez Enum comme paramètre (fortement tapé)
Echo Enum sous forme de chaîne
Obtenez Enum par entier
Obtenez Enum par nom
La classe Enum:
Une addition
Vous pouvez bien sûr également ajouter des commentaires pour les IDE
la source
Je me rends compte que c'est un fil très, très, très ancien, mais j'y ai réfléchi et je voulais savoir ce que les gens pensaient.
Notes: Je jouais avec cela et j'ai réalisé que si je venais de modifier la
__call()
fonction, vous pouvez vous rapprocher encore plus de la réalitéenums
. La__call()
fonction gère tous les appels de fonction inconnus.enums
Supposons donc que vous souhaitiez créer trois RED_LIGHT, YELLOW_LIGHT et GREEN_LIGHT. Vous pouvez le faire maintenant en procédant simplement comme suit:Une fois définis, il vous suffit de les rappeler pour obtenir les valeurs:
et vous devriez obtenir 0, 1 et 2. Amusez-vous! C'est également maintenant sur GitHub.
Mise à jour: je l'ai fait pour que les fonctions
__get()
et__set()
soient maintenant utilisées. Ceux-ci vous permettent de ne pas avoir à appeler une fonction à moins que vous ne le souhaitiez. Au lieu de cela, maintenant vous pouvez simplement dire:Pour la création et l'obtention des valeurs. Parce que les variables n'ont pas été définies initialement, la
__get()
fonction est appelée (car il n'y a pas de valeur spécifiée) qui voit que l'entrée dans le tableau n'a pas été effectuée. Il effectue donc l'entrée, lui attribue la dernière valeur donnée plus un (+1), incrémente la dernière variable de valeur et renvoie VRAI. Si vous définissez la valeur:Puis le
__set()
fonction est appelée et la dernière valeur est ensuite définie sur la nouvelle valeur plus un (+1). Alors maintenant, nous avons un assez bon moyen de faire des énumérations et elles peuvent être créées à la volée.la source
Je sais que c'est un vieux fil, mais aucune des solutions de contournement que j'ai vues ne ressemblait vraiment à des énumérations, car presque toutes les solutions de contournement vous obligent à attribuer manuellement des valeurs aux éléments d'énumération, ou vous obligent à passer un tableau de clés d'énumération à un une fonction. J'ai donc créé ma propre solution pour cela.
Pour créer une classe enum en utilisant ma solution, on peut simplement étendre cette classe Enum ci-dessous, créer un tas de variables statiques (pas besoin de les initialiser), et faire un appel à yourEnumClass :: init () juste en dessous de la définition de votre classe enum .
edit: Cela ne fonctionne que dans php> = 5.3, mais il peut probablement être modifié pour fonctionner également dans les anciennes versions
la source
Vous pouvez maintenant utiliser la classe SplEnum pour la créer en mode natif. Selon la documentation officielle.
Veuillez noter qu'il s'agit d'une extension qui doit être installée, mais qui n'est pas disponible par défaut. Qui relève des types spéciaux décrits dans le site Web php lui-même. L'exemple ci-dessus est tiré du site PHP.
la source
Enfin, une réponse PHP 7.1+ avec des constantes qui ne peuvent pas être remplacées.
Si vous utilisez des espaces de noms, la complétion de code devrait fonctionner.
Cependant, ce faisant, vous perdez la possibilité de masquer les constantes au sein de la famille de classes (
protected
) ou de la classe seule (private
). Par définition, tout dans unInterface
estpublic
.Manuel PHP: Interfaces
la source
Ceci est mon point de vue sur l'énumération "dynamique" ... afin que je puisse l'appeler avec des variables, ex. à partir d'un formulaire.
regardez la version mise à jour sous ce bloc de code ...
MISE À JOUR: Meilleure façon de le faire ...
Appeler avec
la source
EnumCategory::$sport = 9;
. Bienvenue au musée du sport.const
est la meilleure façon de le faire.La réponse acceptée est la voie à suivre et est en fait ce que je fais pour plus de simplicité. La plupart des avantages de l'énumération sont offerts (lisibles, rapides, etc.). Un concept manque cependant: la sécurité de type. Dans la plupart des langues, les énumérations sont également utilisées pour restreindre les valeurs autorisées. Voici un exemple de la façon dont la sécurité de type peut également être obtenue en utilisant des constructeurs privés, des méthodes d'instanciation statique et une vérification de type:
On pourrait même aller plus loin: l'utilisation de constantes dans la classe DaysOfWeek pourrait conduire à une mauvaise utilisation: par exemple, on pourrait l'utiliser à tort de cette façon:
ce qui est faux (appelle constante entière). Nous pouvons éviter cela en utilisant des variables statiques privées au lieu de constantes:
Bien sûr, il n'est pas possible d'accéder aux constantes entières (c'était en fait le but). La méthode intVal permet de convertir un objet DaysOfWeek en sa représentation entière.
Notez que nous pourrions même aller plus loin en implémentant un mécanisme de mise en cache dans les méthodes d'instanciation pour économiser de la mémoire dans le cas où les énumérations sont largement utilisées ...
J'espère que cela vous aidera
la source
Quelques bonnes solutions ici!
Voici ma version.
Je pense que le principal inconvénient est que les membres enum doivent être déclarés et instanciés séparément, en raison des descriptions et de l'incapacité de PHP à construire des objets au moment de la déclaration de membre statique. J'imagine qu'un moyen de contourner cela pourrait être d'utiliser la réflexion avec des commentaires de doc analysés à la place.
L'énumération abstraite ressemble à ceci:
Voici un exemple d'énumération concrète:
Qui peut être utilisé comme ceci:
Et produit cette sortie:
la source
N'utilisez pas la réflexion. Cela rend extrêmement difficile de raisonner sur votre code et de localiser où quelque chose est utilisé, et a tendance à casser les outils d'analyse statique (par exemple ce qui est intégré à votre IDE).
la source
L'un des aspects manquant dans certaines des autres réponses ici est une façon d'utiliser les énumérations avec des indications de type.
Si vous définissez votre énumération comme un ensemble de constantes dans une classe abstraite, par exemple
alors vous ne pouvez pas taper hint it dans un paramètre de fonction - pour un, parce qu'il n'est pas instanciable, mais aussi parce que le type de
ShirtSize::SMALL
estint
, nonShirtSize
.C'est pourquoi les énumérations natives en PHP seraient bien meilleures que tout ce que nous pouvons trouver. Cependant, nous pouvons approximer une énumération en conservant une propriété privée qui représente la valeur de l'énumération, puis en restreignant l'initialisation de cette propriété à nos constantes prédéfinies. Pour éviter que l'énumération soit instanciée arbitrairement (sans la surcharge de vérification de type d'une liste blanche), nous rendons le constructeur privé.
Ensuite, nous pouvons utiliser
ShirtSize
comme ceci:De cette façon, la plus grande différence du point de vue de l'utilisateur est que vous devez virer de bord sur
()
le nom de la constante.Cependant, un inconvénient est que
===
(qui compare l'égalité des objets) retournera false lorsqu'il==
retourne true. Pour cette raison, il est préférable de fournir uneequals
méthode, afin que les utilisateurs n'aient pas à se rappeler d'utiliser==
et de ne===
pas comparer deux valeurs d'énumération.EDIT: Quelques réponses existantes sont très similaires, en particulier: https://stackoverflow.com/a/25526473/2407870 .
la source
En marchant sur la réponse de @Brian Cline, je pensais que je pourrais donner mes 5 cents
la source
include('enums.php');
]. Pour une raison quelconque, il ne voit pas les fonctions déclarées dans Enum pour les classes enfants ...$currentSeason.set("Spring");
Ma tentative de créer une énumération avec PHP ... est extrêmement limitée car elle ne prend pas en charge les objets en tant que valeurs d'énumération, mais reste quelque peu utile ...
la source
Hier, j'ai écrit ce cours sur mon blog . Je pense que c'est peut-être facile à utiliser dans les scripts php:
Usage:
la source