1186 votos

PHP y Enumeraciones

Sé que PHP no tiene Enumeraciones nativas. Pero me he acostumbrado a ellas desde el mundo de Java. Me encantaría usar las enumeraciones como una forma de dar valores predefinidos que las características de autocompletado de los IDEs pudieran entender.

Las constantes hacen el truco, pero existe el problema de la colisión de espacios 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 IDEs raramente (¿nunca?) saben cómo autocompletar sus claves.

¿Hay alguna solución/resolución que utilices habitualmente? ¿Alguien recuerda si los chicos de PHP han tenido alguna idea o decisión sobre los enums?

1531voto

Brian Cline Puntos 8904

Dependiendo del caso de uso, normalmente utilizaría algo simple como lo siguiente:

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

$today = DaysOfWeek::Sunday;

Sin embargo, otros casos de uso pueden requerir una mayor validación de las constantes y los valores. Basándonos en los comentarios sobre la reflexión, y algunas otras notas En este caso, se trata de un ejemplo ampliado que puede servir para una gama mucho más amplia de casos:

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);
    }
}

Creando una simple clase enum que extienda a BasicEnum, ahora tienes la capacidad de usar métodos así para una simple validación de entrada:

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

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 un enum), almaceno en caché los resultados de esas llamadas de reflexión, ya que el uso de objetos de reflexión frescos cada vez tendrá eventualmente un impacto notable en el rendimiento (Almacenado en un Array asociativo para múltiples enums).

Ahora que la mayoría de la gente tiene finalmente actualizado al menos a 5.3, y SplEnum es una opción viable, siempre y cuando no le importe la noción tradicionalmente poco intuitiva de tener un enum instancias en todo su código base. En el ejemplo anterior, BasicEnum y DaysOfWeek no pueden ser instanciados en absoluto, ni deberían serlo.

189voto

markus Puntos 22871

También hay una extensión nativa. La página web SplEnum

SplEnum da la capacidad de emular y crear objetos de enumeración de forma nativa en PHP.

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

Atención:

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

La extensión PECL no está incluida en PHP.

Actualmente no existe una DLL para esta extensión PECL.

48voto

Peter Bailey Puntos 62125

¿Qué pasa con las constantes de clase?

<?php

class YourClass
{
    const SOME_CONSTANT = 1;

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

echo YourClass::SOME_CONSTANT;

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

30voto

andy.gurin Puntos 1516

He utilizado clases con constantes:

class Enum {
    const NAME       = 'aaaa';
    const SOME_VALUE = 'bbbb';
}

print Enum::NAME;

26voto

Andi T Puntos 464

Yo uso interface en lugar de class :

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

var $today = DaysOfWeek::Sunday;

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X