#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;
Комментариев нет:
Отправить комментарий