Pull to refresh

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

Reading time 2 min
Views 18K
Часто ли вам приходилось сожалеть о том, что в 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 ( constant( "{$class_name}::{$type}" )  === NULL ) {
            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


З.Ы. А вот когда выйдет релиз PHP5.3, то можно будет добавить к класс Enum метод:
public static method asArray() {}

который будет возвращать все пары: ключ-значение
оригинал
Tags:
Hubs:
+35
Comments 54
Comments Comments 54

Articles