Страницы

Поиск по вопросам

воскресенье, 16 февраля 2020 г.

Php. Traits. Constants

#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;

Комментариев нет:

Отправить комментарий