Ich weiß, dass PHP keine nativen Aufzählungen hat. Aber ich habe mich aus der Java-Welt an sie gewöhnt. Ich würde gerne Aufzählungen verwenden, um vordefinierte Werte anzugeben, die die Funktionen zur automatischen Vervollständigung von IDEs verstehen könnten.
Konstanten machen den Trick, aber es gibt das Problem der Namespace-Kollision und (oder eigentlich, weil ) sie global sind. Arrays haben kein Namespace-Problem, aber sie sind zu vage, sie können zur Laufzeit überschrieben werden und IDEs wissen selten (nie?), Wie sie ihre Schlüssel automatisch ausfüllen.
Gibt es Lösungen / Problemumgehungen, die Sie üblicherweise verwenden? Erinnert sich jemand daran, ob die PHP-Leute irgendwelche Gedanken oder Entscheidungen in Bezug auf Aufzählungen hatten?
quelle
Antworten:
Abhängig vom Anwendungsfall würde ich normalerweise etwas Einfaches wie das folgende verwenden:
Andere Anwendungsfälle erfordern jedoch möglicherweise eine stärkere Validierung von Konstanten und Werten. Basierend auf den Kommentaren unten zur Reflexion und einigen anderen Anmerkungen ist hier ein erweitertes Beispiel, das möglicherweise eine viel größere Bandbreite von Fällen besser bedienen kann:
Durch das Erstellen einer einfachen Enum-Klasse, die BasicEnum erweitert, haben Sie jetzt die Möglichkeit, Methoden auf diese Weise für die einfache Eingabevalidierung zu verwenden:
Als Randnotiz: Jedes Mal, wenn ich mindestens einmal eine Reflexion für eine statische / konstante Klasse verwende, in der sich die Daten nicht ändern (z. B. in einer Aufzählung), werden die Ergebnisse dieser Reflexionsaufrufe zwischengespeichert, da jedes Mal neue Reflexionsobjekte verwendet werden wird sich irgendwann spürbar auf die Leistung auswirken (in einem assocciative Array für mehrere Aufzählungen gespeichert).
Jetzt, da die meisten Benutzer endlich ein Upgrade auf mindestens 5.3 durchgeführt haben und
SplEnum
verfügbar sind, ist dies sicherlich auch eine praktikable Option - solange Sie nichts gegen die traditionell nicht intuitive Vorstellung haben, tatsächliche Enum- Instanziierungen in Ihrer gesamten Codebasis zu haben. In dem obigen BeispielBasicEnum
undDaysOfWeek
kann überhaupt nicht instanziert werden, noch sollten sie sein.quelle
abstract
und zufinal
erstellen, damit sie nicht instanziiert oder erweitert werden kann.abstract
undfinal
? Ich weiß, dass dies in Java nicht erlaubt ist. Sie können das in PHP tun?abstract
und machen könnenfinal
. In diesem Fall würde ich mich für eine Zusammenfassung entscheiden.null
und Freunde in einerswitch
Aussage. War dort.Es gibt auch eine native Erweiterung. Das SplEnum
http://www.php.net/manual/en/class.splenum.php
Beachtung:
https://www.php.net/manual/en/spl-types.installation.php
quelle
Was ist mit Klassenkonstanten?
quelle
echoConstant
kann durch ersetzt werden__toString
. Und dann einfachecho $c
Die Top-Antwort oben ist fantastisch. Wenn Sie
extend
es jedoch auf zwei verschiedene Arten tun, wird der Cache erstellt, unabhängig davon, welche Erweiterung zuerst ausgeführt wird. Dieser Cache wird dann von allen nachfolgenden Aufrufen verwendet, unabhängig davon, von welcher Nebenstelle die Aufrufe initiiert werden ...Um dies zu lösen, ersetzen Sie die Variable und die erste Funktion durch:
quelle
Ich habe Klassen mit Konstanten verwendet:
quelle
Ich benutze
interface
anstelle vonclass
:quelle
class Foo implements DaysOfWeek { }
und dannFoo::Sunday
... was?class
(oderinterface
, was nur eine Frage der Präferenz ist).Ich habe einige der anderen Antworten hier kommentiert, also dachte ich, ich würde auch abwägen. Letztendlich können Sie, da PHP keine typisierten Aufzählungen unterstützt, auf zwei Arten vorgehen: typisierte Aufzählungen hacken oder damit leben, dass es äußerst schwierig ist, sie effektiv zu hacken.
Ich lebe lieber mit der Tatsache und verwende stattdessen die
const
Methode, die andere Antworten hier auf die eine oder andere Weise verwendet haben:Eine beispielhafte Aufzählung:
Die Verwendung
Enum
als Basisklasse , von der alle anderen Aufzählungen erweitern ermöglicht Hilfsmethoden, wietoArray
,isValid
und so weiter. Für mich sind getippte Aufzählungen ( und die Verwaltung ihrer Instanzen ) einfach zu chaotisch.Hypothetisch
Wenn es eine
__getStatic
magische Methode gäbe ( und vorzugsweise auch eine__equals
magische Methode ), könnte ein Großteil davon mit einer Art Multitonenmuster gemildert werden.( Das Folgende ist hypothetisch; es wird nicht funktionieren, obwohl es vielleicht eines Tages funktionieren wird )
quelle
Nun, für ein einfaches Java wie Enum in PHP verwende ich:
Und um es zu nennen:
Aber ich bin ein PHP-Anfänger und habe Probleme mit der Syntax, daher ist dies möglicherweise nicht der beste Weg. Ich habe einige mit Klassenkonstanten experimentiert, wobei Reflection verwendet wurde, um den Konstantennamen aus seinem Wert zu ermitteln.
quelle
Vier Jahre später bin ich wieder darauf gestoßen. Mein aktueller Ansatz ist dies, da er die Vervollständigung des Codes in der IDE sowie die Typensicherheit ermöglicht:
Basisklasse:
Beispiel Enum:
Anwendungsbeispiel:
Beachten Sie, dass alle Instanzen desselben Enum-Eintrags gleich sind:
Sie können es auch in einer switch-Anweisung verwenden:
Sie können einen Aufzählungseintrag auch nach Name oder Wert erstellen:
Oder Sie können den Namen (dh den Funktionsnamen) einfach aus einem vorhandenen Aufzählungseintrag abrufen:
quelle
const Monday = DaysOfWeek('Monday');
Ich habe diese Bibliothek auf Github gefunden und denke, sie bietet eine sehr anständige Alternative zu den Antworten hier.
PHP Enum Implementierung implementiert von SplEnum
function setAction(Action $action) {
format
,parse
, ...)final
, um dies zu verhindern).Erklärung
Verwendungszweck
Typ-Hinweis-Enum-Werte:
quelle
enum
in PHP 7.x hinzugefügt wird), da sie Typhinweise ermöglicht.__toString()
ermöglicht es Ihnen aufgrund der Magie, mit Aufzählungen das zu tun, was Sie im Allgemeinen wirklich wollen - verwenden Sie sie in einerswitch
oder-if
Anweisung und vergleichen Sie sie direkt mit den Werten der Konstanten. Der beste Ansatz ohne native Enum-Unterstützung, IMO.Wenn Sie Aufzählungen verwenden müssen, die global eindeutig sind (dh auch beim Vergleichen von Elementen zwischen verschiedenen Aufzählungen) und einfach zu verwenden sind, können Sie den folgenden Code verwenden. Ich habe auch einige Methoden hinzugefügt, die ich nützlich finde. Beispiele finden Sie in den Kommentaren ganz oben im Code.
quelle
eval()
nur, damit Sie neue Enums-Laufzeit deklarieren können? Eek. Ich fühle es nicht. Wie verhindern Sie, dass andere Klassen eine falsche Enum-Klasse erstellen, bevor Sie die richtige definieren? Sind die Enums nicht vor der Laufzeit bekannt? Und wie @corsiKa angedeutet hat, keine automatische Vervollständigung der IDE. Der einzige Vorteil, den ich sehe, ist die verzögerte Codierung.Ich mag auch Aufzählungen von Java und aus diesem Grund schreibe ich meine Aufzählungen auf diese Weise. Ich denke, dies ist das ähnlichste Verhalten wie in Java-Aufzählungen. Wenn einige mehr Methoden aus Java verwenden möchten, sollten Sie es hier oder in schreiben abstrakte Klasse, aber Kernidee ist in Code unten eingebettet
quelle
FruitsEnum::Apple()
überFruitsEnum::$Apple
, aber der wichtigere Grund ist , damit niemand sonst von Einstellung$APPLE
, so dass die Enum für die gesamte Anwendung zu brechen. Das andere ist ein einfaches privates statisches Flag$initialized
, das sicherstellt, dass das Anrufeninit()
nach dem ersten Aufruf nicht mehr möglich ist (damit kann sich auch niemand damit anlegen)..init()
ist komisch, und mir macht der Getter-Ansatz nichts aus.quelle
Es könnte so einfach sein wie
in der Zukunft.
PHP RFC: Aufzählungstypen
quelle
Die häufigste Lösung, die ich für Aufzählungen in PHP gesehen habe, bestand darin, eine generische Aufzählungsklasse zu erstellen und diese dann zu erweitern. Vielleicht haben Sie einen Blick auf nehmen diese .
UPDATE: Alternativ habe ich dies von phpclasses.org gefunden.
quelle
Hier ist eine Github-Bibliothek für die Behandlung typsicherer Aufzählungen in PHP:
Diese Bibliothek verwaltet die Generierung von Klassen, das Zwischenspeichern von Klassen und implementiert das Entwurfsmuster Type Safe Enumeration mit verschiedenen Hilfsmethoden für den Umgang mit Aufzählungen, z. B. das Abrufen einer Ordnungszahl zum Sortieren von Aufzählungen oder das Abrufen eines Binärwerts für Aufzählungskombinationen.
Der generierte Code verwendet eine einfache alte PHP-Vorlagendatei, die ebenfalls konfigurierbar ist, sodass Sie Ihre eigene Vorlage bereitstellen können.
Es ist ein vollständiger Test, der mit phpunit abgedeckt ist.
PHP-Enums auf Github (zögern Sie nicht)
Verwendung: (@see usage.php oder Unit-Tests für weitere Details)
Ausgabe:
quelle
Ich habe mich für den folgenden Ansatz entschieden, da ich die Möglichkeit habe, Typensicherheit für Funktionsparameter, automatische Vervollständigung in NetBeans und gute Leistung zu gewährleisten. Das einzige, was ich nicht besonders mag, ist, dass Sie
[extended class name]::enumerate();
nach der Definition der Klasse aufrufen müssen .quelle
DaysOfWeek::$MONDAY = 3;
[extended class name]::enumerate();
nach der Definition aufrufen , warum tun Sie das nicht im Konstrukt?Meine unten stehende Enum-Klassendefinition ist stark typisiert und sehr natürlich zu verwenden und zu definieren.
Definition:
Enum umschalten
Übergabe von Enum als Parameter (stark typisiert)
Echo Enum als String
Holen Sie sich Enum durch Ganzzahl
Holen Sie sich Enum nach Namen
Die Enum-Klasse:
Zusatz
Sie können natürlich auch Kommentare für IDEs hinzufügen
quelle
Mir ist klar, dass dies ein sehr, sehr, sehr alter Thread ist, aber ich hatte einen Gedanken darüber und wollte wissen, was die Leute dachten.
Anmerkungen: Ich habe damit herumgespielt und festgestellt,
__call()
dass Sie der tatsächlichen Funktion noch näher kommen können , wenn ich sie nur modifiziereenums
. Die__call()
Funktion verarbeitet alle unbekannten Funktionsaufrufe.enums
Angenommen, Sie möchten drei RED_LIGHT, YELLOW_LIGHT und GREEN_LIGHT erstellen. Sie können dies jetzt tun, indem Sie einfach Folgendes tun:Einmal definiert, müssen Sie sie nur noch einmal aufrufen, um die Werte zu erhalten:
und du solltest 0, 1 und 2 bekommen. Viel Spaß! Dies ist jetzt auch auf GitHub verfügbar.
Update: Ich habe es so gemacht, dass jetzt sowohl die
__get()
als auch die__set()
Funktionen verwendet werden. Mit diesen können Sie keine Funktion aufrufen müssen, es sei denn, Sie möchten. Stattdessen können Sie jetzt einfach sagen:Sowohl für die Schaffung als auch für das Erhalten der Werte. Da die Variablen anfangs nicht definiert wurden, wird die
__get()
Funktion aufgerufen (da kein Wert angegeben ist), wodurch festgestellt wird, dass der Eintrag im Array nicht vorgenommen wurde. Es macht also den Eintrag, weist ihm den zuletzt angegebenen Wert plus eins (+1) zu, erhöht die letzte Wertvariable und gibt TRUE zurück. Wenn Sie den Wert einstellen:Dann wird die
__set()
Funktion aufgerufen und der letzte Wert auf den neuen Wert plus eins (+1) gesetzt. Jetzt haben wir also eine ziemlich gute Möglichkeit, Aufzählungen zu erstellen, und sie können im laufenden Betrieb erstellt werden.quelle
Ich weiß, dass dies ein alter Thread ist, aber keine der Problemumgehungen, die ich gesehen habe, sah wirklich wie Aufzählungen aus, da bei fast allen Problemumgehungen Sie den Aufzählungselementen manuell Werte zuweisen müssen oder ein Array von Aufzählungsschlüsseln an a übergeben müssen Funktion. Also habe ich meine eigene Lösung dafür geschaffen.
Um eine Enum-Klasse mit meiner Lösung zu erstellen, können Sie diese Enum-Klasse einfach unten erweitern, eine Reihe statischer Variablen erstellen (ohne sie initialisieren zu müssen) und yourEnumClass :: init () direkt unterhalb der Definition Ihrer Enum-Klasse aufrufen .
edit: Dies funktioniert nur in php> = 5.3, kann aber wahrscheinlich auch in älteren Versionen geändert werden
quelle
Jetzt können Sie die SplEnum- Klasse verwenden, um sie nativ zu erstellen. Gemäß der offiziellen Dokumentation.
Bitte beachten Sie, dass es sich um eine Erweiterung handelt, die installiert werden muss, aber standardmäßig nicht verfügbar ist. Welches fällt unter spezielle Typen, die auf der PHP-Website selbst beschrieben sind. Das obige Beispiel stammt von der PHP-Site.
quelle
Schließlich eine Antwort von PHP 7.1+ mit Konstanten, die nicht überschrieben werden können.
Wenn Sie Namespaces verwenden, sollte die Code-Vervollständigung funktionieren.
Dadurch verlieren Sie jedoch die Fähigkeit, die Konstanten innerhalb der Klassenfamilie (
protected
) oder der Klasse allein (private
) auszublenden . Per Definition ist alles in einemInterface
istpublic
.PHP-Handbuch: Schnittstellen
quelle
Dies ist meine Einstellung zu "dynamischer" Aufzählung ... damit ich sie mit Variablen aufrufen kann, z. aus einem Formular.
Schauen Sie sich die aktualisierte Version unter diesem Codeblock an ...
UPDATE: Besser so ...
Rufen Sie an mit
quelle
EnumCategory::$sport = 9;
. Willkommen im Sportmuseum.const
ist der bessere Weg, es zu tun.Die akzeptierte Antwort ist der richtige Weg und ist eigentlich das, was ich der Einfachheit halber tue. Die meisten Vorteile der Aufzählung werden angeboten (lesbar, schnell usw.). Ein Konzept fehlt jedoch: Typensicherheit. In den meisten Sprachen werden Aufzählungen auch verwendet, um zulässige Werte einzuschränken. Im Folgenden finden Sie ein Beispiel dafür, wie die Typensicherheit auch mithilfe privater Konstruktoren, statischer Instanziierungsmethoden und Typprüfung erreicht werden kann:
Wir könnten sogar noch weiter gehen: Die Verwendung von Konstanten in der DaysOfWeek-Klasse kann zu Missbrauch führen: z. B. könnte man sie fälschlicherweise so verwenden:
was falsch ist (ruft Integer-Konstante auf). Wir können dies verhindern, indem wir private statische Variablen anstelle von Konstanten verwenden:
Natürlich ist es nicht möglich, auf ganzzahlige Konstanten zuzugreifen (dies war eigentlich der Zweck). Mit der intVal-Methode kann ein DaysOfWeek-Objekt in seine Ganzzahldarstellung konvertiert werden.
Beachten Sie, dass wir sogar noch weiter gehen könnten, indem wir einen Caching-Mechanismus in Instanziierungsmethoden implementieren, um Speicherplatz zu sparen, falls Aufzählungen häufig verwendet werden ...
Hoffe das wird helfen
quelle
Einige gute Lösungen hier!
Hier ist meine Version.
Ich denke, der Hauptnachteil ist, dass Enum-Mitglieder aufgrund der Beschreibungen und der Unfähigkeit von PHP, Objekte zum Zeitpunkt der Deklaration statischer Mitglieder zu erstellen, separat deklariert und instanziiert werden müssen. Ich denke, ein Weg, dies zu umgehen, könnte darin bestehen, stattdessen Reflexion mit analysierten Dokumentkommentaren zu verwenden.
Die abstrakte Aufzählung sieht folgendermaßen aus:
Hier ist ein konkretes Beispiel:
Welches kann so verwendet werden:
Und erzeugt diese Ausgabe:
quelle
Verwenden Sie keine Reflexion. Dies macht es äußerst schwierig, über Ihren Code nachzudenken und festzustellen, wo etwas verwendet wird, und führt dazu, dass statische Analysewerkzeuge beschädigt werden (z. B. was in Ihre IDE integriert ist).
quelle
Einer der Aspekte, die in einigen der anderen Antworten hier fehlen, ist die Verwendung von Aufzählungen mit Typhinweisen.
Wenn Sie Ihre Aufzählung als eine Menge von Konstanten in einer abstrakten Klasse definieren, z
dann können Sie es nicht in einem Funktionsparameter geben andeuten - für einen, weil es nicht instantiable ist, sondern auch , weil die Art der
ShirtSize::SMALL
istint
, nichtShirtSize
.Deshalb wären native Aufzählungen in PHP so viel besser als alles, was wir uns einfallen lassen können. Wir können eine Aufzählung jedoch approximieren, indem wir eine private Eigenschaft beibehalten, die den Wert der Aufzählung darstellt, und dann die Initialisierung dieser Eigenschaft auf unsere vordefinierten Konstanten beschränken. Um zu verhindern, dass die Aufzählung willkürlich instanziiert wird (ohne den Aufwand für die Typprüfung einer Whitelist), machen wir den Konstruktor privat.
Dann können wir so verwenden
ShirtSize
:Auf diese Weise besteht der größte Unterschied aus der Sicht des Benutzers darin, dass Sie
()
den Namen der Konstante anheften müssen.Ein Nachteil ist jedoch, dass
===
(der die Objektgleichheit vergleicht) false==
zurückgibt, wenn true zurückgegeben wird. Aus diesem Grund ist es am besten, eineequals
Methode anzugeben, damit Benutzer nicht daran denken müssen, zwei Aufzählungswerte zu verwenden==
und nicht===
zu vergleichen.BEARBEITEN: Einige der vorhandenen Antworten sind sehr ähnlich, insbesondere: https://stackoverflow.com/a/25526473/2407870 .
quelle
Als ich auf die Antwort von @Brian Cline trat, dachte ich, ich könnte meine 5 Cent geben
quelle
include('enums.php');
]. Aus irgendeinem Grund werden in Enum keine Funktionen für$currentSeason.set("Spring");
Mein Versuch, eine Aufzählung mit PHP zu erstellen ... ist äußerst begrenzt, da Objekte als Aufzählungswerte nicht unterstützt werden, aber dennoch etwas nützlich sind ...
quelle
Gestern habe ich diese Klasse in meinem Blog geschrieben . Ich denke, es ist vielleicht einfach für die Verwendung in PHP-Skripten:
Verwendungszweck:
quelle