#php #const #traits
Прошу совета толковых программистов. Мне часто не хватает возможности (php 5.6) описывать в трейтах константы. Свойства класса есть, а вот константы не ввели. Собственно 2 вопроса. Главный: Как правильно обеспечить множественное наследование с константами на уровне самого php? Интересует: Почему разработчики не дали возможность подмешивать в классы константы с помощью трейтов? Может это плохая практика... Дополнение: (многие не могут понять "А зачем?") Попробую показать. Есть в БД много таблиц в которых есть поле status: 0 - выкл, 1 - вкл, делаем трейт (зачем создавать таблицу для двух значений?) trait Status { const STATUS_INACTIVE = 0; const STATUS_ACTIVE = 1; public static function getStatuses() { return [ static::STATUS_INACTIVE => 'Inactive', static::STATUS_ACTIVE => 'Active', ]; } public function getStatusLabel($nullLabel = '') { $statuses = static::getStatuses(); return isset($statuses[$this->status]) ? $statuses[$this->status] : $nullLabel; } } getStatuses() используем для выпадающего списка в форме, getStatusLabel() - тут я думаю и так ясно. и это упрощенный пример. также можно создать другие трейты, а потом уже решать какие трейты подключать для какой-то сущности а какие нет. Одним словом мне нужны именно трейты с константами и я не понимаю почему не дали возможность их использовать в php. Конечно я могу извратиться и сделать константы через статические свойства trait Status { protected static $STATUS_INACTIVE = 0; public static function STATUS_INACTIVE() { return static::$STATUS_INACTIVE; } protected static $STATUS_ACTIVE = 1; public static function STATUS_ACTIVE() { return static::$STATUS_ACTIVE; } но хотелось бы понять почему не дали трейтам константы
Ответы
Ответ 1
Трейты в php реализованы, как copy-paste на уровне интерпретатора. Не стоит ими злоупотреблять. Решение не позволять константы в трейтах мотивировано сложностью разрешения коллизий имён констант. Возможно, когда-нибудь эту проблему решат. А пока, ничто не мешает вам написать так: interface IActiveStatus { const STATUS_INACTIVE = 0; const STATUS_ACTIVE = 1; } trait Status { public static function getStatuses() { return [ static::STATUS_INACTIVE => 'Inactive', static::STATUS_ACTIVE => 'Active', ]; } public function getStatusLabel($nullLabel = '') { $statuses = static::getStatuses(); return isset($statuses[$this->status]) ? $statuses[$this->status] : $nullLabel; } } class A implements IActiveStatus { use Status; } или лучше: interface IActiveStatus { const STATUS_INACTIVE = 0; const STATUS_ACTIVE = 1; } trait Status { public static function getStatuses() { return [ IActiveStatus::STATUS_INACTIVE => 'Inactive', IActiveStatus::STATUS_ACTIVE => 'Active', ]; } public function getStatusLabel($nullLabel = '') { $statuses = static::getStatuses(); return isset($statuses[$this->status]) ? $statuses[$this->status] : $nullLabel; } } class A { use Status; } Хотя, я бы порекомендовал немножко пересмотреть интерфейс: trait Status{ protected $status = IActiveStatus::STATUS_INACTIVE; public function isActive() { return $this->status === IActiveStatus::STATUS_ACTIVE; } public function isInactive() { return $this->status === IActiveStatus::STATUS_INACTIVE; } public function setActive() { $this->status = IActiveStatus::STATUS_ACTIVE; } public function setInactive() { $this->status = IActiveStatus::STATUS_INACTIVE; } public function getStatusLabel() { return ([ IActiveStatus::STATUS_ACTIVE => 'Active', IActiveStatus::STATUS_INACTIVE => 'Inactive', ])[$this->status]; } }Ответ 2
Можно не через трейты а через интерфейсы сделать. Отлично вписывается в множественное наследование interface IStatus { const STATUS_ENABLED = 1; const STATUS_DISABLED = 0; } interface IExtStatus { const STATUS_BLOCKED = 2; } class Test implements IStatus, IExtStatus { const STATUS_LOCAL = 3; } echo Test::STATUS_BLOCKED; echo Test::STATUS_LOCAL; echo Test::STATUS_ENABLED;
Комментариев нет:
Отправить комментарий