Sé que PHP no tiene enumeraciones nativas. Pero me he acostumbrado a ellos desde el mundo de Java. Me encantaría usar enumeraciones como una forma de dar valores predefinidos que las características de autocompletado de IDE puedan entender.
Las constantes hacen el truco, pero existe el problema de colisión del espacio de nombres y (o en realidad porque ) son globales. Las matrices no tienen el problema del espacio de nombres, pero son demasiado vagas, pueden sobrescribirse en tiempo de ejecución y los IDE rara vez (¿nunca?) Saben cómo rellenar automáticamente sus claves.
¿Hay alguna solución / solución que utilice comúnmente? ¿Alguien recuerda si los chicos de PHP han tenido alguna idea o decisión sobre las enumeraciones?
php
enumeration
Henrik Paul
fuente
fuente
Respuestas:
Dependiendo del caso de uso, normalmente usaría algo simple como lo siguiente:
Sin embargo, otros casos de uso pueden requerir más validación de constantes y valores. En base a los comentarios a continuación sobre la reflexión, y algunas otras notas , aquí hay un ejemplo ampliado que puede servir mejor para una gama mucho más amplia de casos:
Al crear una clase de enumeración simple que extiende BasicEnum, ahora tiene la capacidad de utilizar métodos para una validación de entrada simple:
Como nota al margen, cada vez que uso la reflexión al menos una vez en una clase estática / constante donde los datos no cambiarán (como en una enumeración), guardo en caché los resultados de esas llamadas de reflexión, ya que uso objetos de reflexión nuevos cada vez eventualmente tendrá un impacto notable en el rendimiento (almacenado en una matriz asociativa para múltiples enumeraciones).
Ahora que la mayoría de las personas finalmente se ha actualizado a al menos 5.3, y
SplEnum
está disponible, esa es ciertamente una opción viable también, siempre y cuando no le importe la noción tradicionalmente no intuitiva de tener instancias de enumeración reales en toda su base de código. En el ejemplo anterior,BasicEnum
yDaysOfWeek
no puede ser instanciado en absoluto, ni deberían serlo.fuente
abstract
yfinal
, por lo tanto, no se puede instanciar o extender.abstract
yfinal
? Sé que en Java esto no está permitido. ¿Puedes hacer eso en php?abstract
yfinal
. En ese caso, iría por el resumen.null
y amigos en unaswitch
declaración. Estado allí.También hay una extensión nativa. El SplEnum
http://www.php.net/manual/en/class.splenum.php
Atención:
https://www.php.net/manual/en/spl-types.installation.php
fuente
¿Qué pasa con las constantes de clase?
fuente
echoConstant
puede ser reemplazado con__toString
. Y luego simplementeecho $c
La respuesta superior anterior es fantástica. Sin embargo, si tu
extend
hace de dos maneras diferentes, cualquiera que sea la extensión que se realice primero da como resultado una llamada a las funciones creará el caché. Este caché será utilizado por todas las llamadas posteriores, sin importar la extensión en que las llamadas sean iniciadas por ...Para resolver esto, reemplace la variable y la primera función con:
fuente
Usé clases con constantes:
fuente
Yo uso en
interface
lugar declass
:fuente
class Foo implements DaysOfWeek { }
y luegoFoo::Sunday
... que?class
(ointerface
, que es solo una cuestión de preferencia).He comentado algunas de las otras respuestas aquí, así que pensé que también me importaría. Al final del día, dado que PHP no admite enumeraciones escritas, puede tomar una de dos formas: cortar las enumeraciones escritas o vivir con el hecho de que son extremadamente difíciles de hackear de manera efectiva.
Prefiero vivir con el hecho, y en su lugar usar el
const
método que otras respuestas aquí han usado de una forma u otra:Un ejemplo de enumeración:
El uso
Enum
como una clase base desde la que se extienden todas las demás enumeraciones permite métodos auxiliares, comotoArray
,isValid
etc. Para mí, las enumeraciones escritas ( y la gestión de sus instancias ) terminan siendo demasiado desordenadas.Hipotético
Si , existía un
__getStatic
método mágico ( y preferiblemente un__equals
método mágico también ), gran parte de esto podría mitigarse con una especie de patrón multitonal.( Lo siguiente es hipotético; no funcionará, aunque quizás algún día lo haga )
fuente
Bueno, para un simple java como enum en php, uso:
Y para llamarlo:
Pero soy un principiante de PHP, luchando con la sintaxis, por lo que esta podría no ser la mejor manera. Experimenté algunos con Constantes de clase, usando Reflection para obtener el nombre constante de su valor, podría ser más ordenado.
fuente
Cuatro años después me encontré con esto nuevamente. Mi enfoque actual es este, ya que permite completar el código en el IDE, así como la seguridad de tipo:
Clase base:
Ejemplo de enumeración:
Ejemplo de uso:
Tenga en cuenta que todas las instancias de la misma entrada enum son iguales:
También puede usarlo dentro de una declaración de cambio:
También puede crear una entrada de enumeración por nombre o valor:
O simplemente puede obtener el nombre (es decir, el nombre de la función) de una entrada enum existente:
fuente
const Monday = DaysOfWeek('Monday');
Encontré esta biblioteca en github y creo que proporciona una alternativa muy decente a las respuestas aquí.
Implementación PHP Enum inspirada en SplEnum
function setAction(Action $action) {
format
,parse
, ...)final
para evitarlo)Declaración
Uso
valores de enumeración de tipo de pista:
fuente
enum
se agregue en PHP 7.x) porque permite sugerencias de tipo.__toString()
magia, te permite hacer lo que generalmente quieres con enumeraciones: úsalas en una declaraciónswitch
oif
, comparándolas directamente con los valores de los consts. El mejor enfoque por debajo del soporte de enumeración nativa, IMO.Si necesita usar enumeraciones que sean globalmente únicas (es decir, incluso al comparar elementos entre diferentes enumeraciones) y que sean fáciles de usar, no dude en usar el siguiente código. También agregué algunos métodos que encuentro útiles. Encontrará ejemplos en los comentarios en la parte superior del código.
fuente
eval()
solo para poder declarar el nuevo tiempo de ejecución de Enums? Eek No lo estoy sintiendo. ¿Cómo evita que otras clases creen una clase Enum incorrecta antes de definir la correcta? ¿No se conocen las enumeraciones antes del tiempo de ejecución? Y como implicaba @corsiKa, no hay autocompletado IDE. El único beneficio que veo es la codificación perezosa.También me gustan las enumeraciones de Java y por esta razón escribo mis enumeraciones de esta manera, creo que este es el comportamiento más similar al de las enumeraciones de Java, por supuesto, si algunos quieren usar más métodos de Java, escríbalo aquí, o en clase abstracta pero la idea central está incrustada en el código a continuación
fuente
FruitsEnum::Apple()
másFruitsEnum::$Apple
, pero la razón más importante es evitar que cualquier otro de ajuste$APPLE
, rompiendo así la enumeración para toda la aplicación. El otro es un indicador estático privado simple$initialized
que asegura que las llamadas seinit()
vuelvan no operativas después de llamar por primera vez (para que nadie pueda meterse con eso tampoco)..init()
es raro, y no me importa el enfoque getter.fuente
Puede ser tan simple como
en el futuro.
PHP RFC: Tipos enumerados
fuente
La solución más común que he visto para enum's en PHP ha sido crear una clase enum genérica y luego extenderla. Puedes echar un vistazo a esto .
ACTUALIZACIÓN: Alternativamente, encontré esto en phpclasses.org.
fuente
Aquí hay una biblioteca github para manejar enumeraciones de tipo seguro en php:
Esta biblioteca maneja la generación de clases, el almacenamiento en caché de clases e implementa el patrón de diseño de enumeración segura de tipo, con varios métodos auxiliares para tratar con enumeraciones, como recuperar un ordinal para ordenar enumeraciones, o recuperar un valor binario, para combinaciones de enumeraciones.
El código generado utiliza un archivo de plantilla php antiguo simple, que también es configurable, por lo que puede proporcionar su propia plantilla.
Es una prueba completa cubierta con phpunit.
php-enums en github (no dude en bifurcar)
Uso: (@ver use.php, o pruebas unitarias para más detalles)
Salida:
fuente
He optado por utilizar el siguiente enfoque, ya que me da la capacidad de tener seguridad de tipo para los parámetros de función, autocompletar en NetBeans y buen rendimiento. Lo único que no me gusta demasiado es que tienes que llamar
[extended class name]::enumerate();
después de definir la clase.fuente
DaysOfWeek::$MONDAY = 3;
[extended class name]::enumerate();
después de la definición, ¿por qué no lo haces en la construcción?Mi definición de clase Enum a continuación está fuertemente tipada y es muy natural de usar y definir.
Definición:
Cambiar Enum
Pase Enum como parámetro (fuertemente tipado)
Echo Enum como cuerda
Consigue Enum por entero
Obtenga Enum por nombre
La clase de Enum:
Adición
Por supuesto, también puede agregar comentarios para IDEs
fuente
Me doy cuenta de que este es un hilo muy, muy antiguo, pero pensé en esto y quise saber qué pensaba la gente.
Notas: Estaba jugando con esto y me di cuenta de que si solo modificaba la
__call()
función, podría acercarse aún más a la realenums
. La__call()
función maneja todas las llamadas a funciones desconocidas. Entonces, digamos que quieres hacer tresenums
RED_LIGHT, YELLOW_LIGHT y GREEN_LIGHT. Puede hacerlo ahora simplemente haciendo lo siguiente:Una vez definido, todo lo que tiene que hacer es llamarlos nuevamente para obtener los valores:
y deberías obtener 0, 1 y 2. ¡Diviértete! Esto también está ahora en GitHub.
Actualización: lo hice para que ahora se utilicen las funciones
__get()
y__set()
. Esto le permite no tener que llamar a una función a menos que lo desee. En cambio, ahora solo puedes decir:Tanto para la creación como para la obtención de los valores. Debido a que las variables no se han definido inicialmente, la
__get()
función se llama (porque no hay un valor especificado) que ve que la entrada en la matriz no se ha realizado. Por lo tanto, realiza la entrada, le asigna el último valor dado más uno (+1), incrementa la última variable de valor y devuelve VERDADERO. Si establece el valor:Luego
__set()
se llama a la función y el último valor se establece en el nuevo valor más uno (+1). Así que ahora tenemos una forma bastante buena de hacer enumeraciones y se pueden crear sobre la marcha.fuente
Sé que este es un hilo antiguo, sin embargo, ninguna de las soluciones que he visto realmente se parecía a enumeraciones, ya que casi todas las soluciones alternativas requieren que asigne valores manualmente a los elementos de enumeración, o requiere que pase una matriz de claves de enumeración a un función. Entonces creé mi propia solución para esto.
Para crear una clase enum usando mi solución, simplemente puede extender esta clase Enum a continuación, crear un grupo de variables estáticas (no es necesario inicializarlas) y hacer una llamada a yourEnumClass :: init () justo debajo de la definición de su clase enum .
editar: esto solo funciona en php> = 5.3, pero probablemente también se pueda modificar para que funcione en versiones anteriores
fuente
Ahora puedes usar El clase SplEnum para construirla de forma nativa. Según la documentación oficial.
Tenga en cuenta que es una extensión que debe instalarse, pero que no está disponible de forma predeterminada. Que viene bajo Tipos especiales descritos en el sitio web php. El ejemplo anterior está tomado del sitio PHP.
fuente
Finalmente, una respuesta de PHP 7.1+ con constantes que no se pueden anular.
Si está utilizando espacios de nombres, la finalización del código debería funcionar.
Sin embargo, al hacer esto, pierde la capacidad de ocultar las constantes dentro de la familia de clases (
protected
) o la clase sola (private
). Por definición, todo en unInterface
espublic
.Manual PHP: Interfaces
fuente
Esta es mi opinión sobre la enumeración "dinámica" ... para poder llamarla con variables, ej. de un formulario.
mira la versión actualizada debajo de este bloque de código ...
ACTUALIZACIÓN: Mejor forma de hacerlo ...
Llamar con
fuente
EnumCategory::$sport = 9;
. Bienvenido al museo del deporte.const
Es la mejor manera de hacerlo.La respuesta aceptada es el camino a seguir y en realidad es lo que estoy haciendo por simplicidad. Se ofrecen la mayoría de las ventajas de la enumeración (legible, rápida, etc.). Sin embargo, falta un concepto: tipo de seguridad. En la mayoría de los idiomas, las enumeraciones también se usan para restringir los valores permitidos. A continuación se muestra un ejemplo de cómo la seguridad de tipos también se puede obtener mediante el uso de constructores privados, métodos de creación de instancias estáticas y verificación de tipos:
Incluso podríamos ir más allá: el uso de constantes en la clase DaysOfWeek podría provocar un mal uso: por ejemplo, uno podría usarlo por error de esta manera:
que está mal (llama a entero constante). Podemos evitar esto usando variables privadas estáticas en lugar de constantes:
Por supuesto, no es posible acceder a constantes enteras (este era realmente el propósito). El método intVal permite convertir un objeto DaysOfWeek a su representación entera.
Tenga en cuenta que incluso podríamos ir más allá implementando un mecanismo de almacenamiento en caché en los métodos de creación de instancias para ahorrar memoria en el caso de que las enumeraciones se utilicen ampliamente ...
Espero que esto ayude
fuente
¡Algunas buenas soluciones aquí!
Aquí está mi versión.
Creo que la principal desventaja es que los miembros de enumeración deben declararse e instanciarse por separado, debido a las descripciones y la incapacidad de PHP para construir objetos en el tiempo de declaración de miembro estático. Supongo que una forma de evitar esto podría ser utilizar la reflexión con comentarios de documentos analizados en su lugar.
La enumeración abstracta se ve así:
Aquí hay un ejemplo de enumeración concreta:
Que se puede usar así:
Y produce esta salida:
fuente
No uses la reflexión. Hace que sea extremadamente difícil razonar sobre su código y rastrear dónde se está usando algo, y tiende a romper las herramientas de análisis estático (por ejemplo, lo que está integrado en su IDE).
fuente
Uno de los aspectos que faltan en algunas de las otras respuestas aquí es una forma de usar enumeraciones con sugerencias de tipo.
Si define su enumeración como un conjunto de constantes en una clase abstracta, por ejemplo
entonces no se puede escribir insinuar que en función de un parámetro - por un lado, porque no es instanciable, sino también por el tipo de
ShirtSize::SMALL
esint
, noShirtSize
.Es por eso que las enumeraciones nativas en PHP serían mucho mejores que cualquier cosa que se nos ocurra. Sin embargo, podemos aproximar una enumeración manteniendo una propiedad privada que represente el valor de la enumeración y luego restringiendo la inicialización de esta propiedad a nuestras constantes predefinidas. Para evitar que la enumeración se instancia de forma arbitraria (sin la sobrecarga de la verificación de tipo de una lista blanca), hacemos que el constructor sea privado.
Entonces podemos usar
ShirtSize
así:De esta manera, la mayor diferencia desde la perspectiva del usuario es que debe agregar un
()
a la constante.Sin embargo, una desventaja es que
===
(que compara la igualdad de objetos) devolverá falso cuando==
devuelva verdadero. Por esa razón, es mejor proporcionar unequals
método, para que los usuarios no tengan que acordarse de usar==
y no===
comparar dos valores de enumeración.EDITAR: Algunas de las respuestas existentes son muy similares, particularmente: https://stackoverflow.com/a/25526473/2407870 .
fuente
Al pisar la respuesta de @Brian Cline, pensé que podría dar mis 5 centavos
fuente
include('enums.php');
]. Por alguna razón, no ve las funciones declaradas en Enum para las clases infantiles ...$currentSeason.set("Spring");
Mi intento de crear una enumeración con PHP ... es extremadamente limitado ya que no admite objetos como los valores de enumeración, pero sigue siendo algo útil ...
fuente
Ayer escribí esta clase en mi blog . Creo que puede ser fácil de usar en scripts php:
Uso:
fuente