Перечисления в PHP

Часто ли вам приходилось сожалето о том, что в PHP нет перечислений как таковых?

Да, кто-то обходился конвенцией именования и получалось нечто вроде:

define( 'COLOR_RED', 'F00' );
define( 'COLOR_GREEN', '0F0' );
define( 'COLOR_BLUE', '00F' );

Или нечто вроде:

// данную переменную ЗАПРЕЩЕНО модифицировать
$colors = array(
    'red' => 'F00',
    'green' => '0F0',
    'blue' => '00F',
);

Но оба подхода имеют существенные недостатки:

  • В первом случае члены перечисления не образуют явной группировки
  • Во втором случае есть риск что переменная будет изменена
  • И в обоих этих случаях мы не можем делать проверку на тип переменной (type hinting)

Под катом предлагаю решение без вышеописанных недостатков…

abstract class Enum {
    private $current_val;

    final public function __construct( $type ) {
        $class_name = get_class( $this );

        $type = strtoupper( $type );
        if ( NULL === constant( "{$class_name}::{$type}" ) ) {
            throw new Enum_Exception( 'Свойства '.$type.' в перечислении '.$class_name.' не найдено.' );
        }

        $this->current_val = constant( "{$class_name}::{$type}" );
    }

    final public function __toString() {
        return $this->current_val;
    }
}

class Enum_Exception extends Exception {}

Это базовый класс для перечислений. При работе нам надо будет только подключить его и в дальнейшем можно о нем забыть.

Ну а что бы реализовать сами перечисления, нам необходимо написать подобную структуру:

class Enum_Colors extends Enum {
    const RED = 'F00';
    const GREEN = '0F0';
    const BLUE = '00F';
}

И теперь что бы обращаться к константному значению и использовать type hinting нам надо создать объект из данного класса, передав в конструктор имя необходимой константы:

function setColor( Enum_Colors $color ) {
    echo $color;
}
setColor( new Enum_Colors( 'GREEN' ) ); // will pass
setColor( '0F0' ); // won't pass

Enum_Colors::RED == new Enum_Colors( 'GREEN' ); // FALSE

Enum_Colors::RED == new Enum_Colors( 'RED' ); // TRUE

Tags: , , , ,

Также рекомендую к прочтению:

Leave a Reply

Введите следующие символы: