Проблема заключалась в следующем. Необходимо реализовать функцию, которая бы на вход принимала строго типизированный объект (класс), однако в теле функций необходим перебор значений данного класса и сравнение его с предопределенными константами (этого же класса):
function test(Data $data) { switch ((string)$data) { case Data::ID: echo 'This is ID' . PHP_EOL; break; case Data::STRING: echo 'This is a STRING' . PHP_EOL; break; } }
Однако, сразу становится очевидным, что PHP выдаст предупреждение о том, что невозможно использовать объект в качестве параметра оператора switch
.
Решение проблемы состоит в том, чтобы реализовать абстрактный класс, в качестве базового для всех классов, где будут использоваться предопределенные константы, с которыми и будет происходить сравнение в операторе switch
.
Код данного класса:
/** * Base class, witch implements enumeration in child classes. * * PHP version 5 * * @author Andrey Klimenko * @license 2012, Andrey Klimenko * @version 1.0.0 */ abstract class AbstractEnum { /** * @var AbstractEnum Class instance */ protected static $instance = null; /** * @var mixed Value to compare with class constants */ protected static $value; /** * Protected constructor (realize singleton pattern). * * @final */ protected final function __construct() { } /** * Protect from object cloning (realize singleton pattern). * * @final */ protected final function __clone() { } /** * Protect from reconstruct resources that the object may have (realize singleton pattern). * * @final */ protected final function __wakeup() { } /** * Return instance of this object. * * @static * * @param mixed $value Constant value * * @return AbstractEnum */ public static function getInstance($value) { if (self::$instance === null) { self::$instance = new static(); } self::setConstant($value); // Set value of constant return self::$instance; } /** * Prepare to return constant value, given in getInstance() function. * * @return string */ public final function __toString() { return (string)static::$value; } /** * Set constant value. * * @static * * @param mixed $value Constant value * */ protected static function setConstant($value) { $class = new \ReflectionClass(static::$instance); // Get this class reflection $constants = array_flip($class->getConstants()); // Get constants of this object // Check if constant with given value exist if (array_key_exists($value, $constants)) { $constantName = $constants[$value]; static::$value = $class->getConstant($constantName); // Set constant value } else { trigger_error('Class does not have constant with this value: `' . $value . '`', E_USER_ERROR); } } }
Теперь реализуем класс, который наследуется от абстрактного класса, описанного выше. Данный класс является классом, который включает в себя константы, с которыми мы и будем производить сравнение.
/** * Sample class, witch implement AbstractEnum abstract class. * * PHP version 5 * * @author Andrey Klimenko * @license 2012, Andrey Klimenko * @version 1.0.0 */ class Data extends AbstractEnum { const ID = 1; // First constant const STRING = 2; // Second constant }
Теперь реализуем функцию, в которой проверим работу нашего класса. Основной проблемой, как я уже сказал была строгая типизация параметра, передаваемого в нее. В качестве типа мы и указываем наш класс Data
.
/** * Test function. * * @param Data $data Class to check value with. * * @return void */ function test(Data $data) { // First - convert object to string switch ((string)$data) { // compare needed values case Data::ID: echo 'This is ID' . PHP_EOL; break; case Data::STRING: echo 'This is a STRING' . PHP_EOL; break; } }
И последнее – проверим нашу функцию:
for ($i = 1; $i < 3; $i++) { test(Data::getInstance($i)); }
Все работает, как мы и хотели. На этом все. Надеюсь кому-то данная конструкция пригодится.
ссылка на оригинал статьи http://habrahabr.ru/post/173311/
Добавить комментарий