behavior.md 6.7 KB

Behavior

Behavior - это объекты, которые позволяют расширять базовую функциональность классов Yii2 без перенаследования оных, используя магические __get и __call.

Определение класса поведения

class TimestampBehavior extends AttributeBehavior
{
    /**
     * @var string the attribute that will receive timestamp value
     * Set this property to false if you do not want to record the creation time.
     */
    public $createdAtAttribute = 'created_at';
    /**
     * @var string the attribute that will receive timestamp value.
     * Set this property to false if you do not want to record the update time.
     */
    public $updatedAtAttribute = 'updated_at';
    /**
     * @inheritdoc
     *
     * In case, when the value is `null`, the result of the PHP function [time()](http://php.net/manual/en/function.time.php)
     * will be used as value.
     */
    public $value;
    /**
     * @inheritdoc
     */
    public function init()
    {
        parent::init();
        if (empty($this->attributes)) {
            $this->attributes = [
                BaseActiveRecord::EVENT_BEFORE_INSERT => [$this->createdAtAttribute, $this->updatedAtAttribute],
                BaseActiveRecord::EVENT_BEFORE_UPDATE => $this->updatedAtAttribute,
            ];
        }
    }
    /**
     * @inheritdoc
     *
     * In case, when the [[value]] is `null`, the result of the PHP function [time()](http://php.net/manual/en/function.time.php)
     * will be used as value.
     */
    protected function getValue($event)
    {
        if ($this->value === null) {
            return time();
        }
        return parent::getValue($event);
    }
    /**
     * Updates a timestamp attribute to the current timestamp.
     *
     * ```php
     * $model->touch('lastVisit');
     * ```
     * @param string $attribute the name of the attribute to update.
     * @throws InvalidCallException if owner is a new record (since version 2.0.6).
     */
    public function touch($attribute)
    {
        /* @var $owner BaseActiveRecord */
        $owner = $this->owner;
        if ($owner->getIsNewRecord()) {
            throw new InvalidCallException('Updating the timestamp is not possible on a new record.');
        }
        $owner->updateAttributes(array_fill_keys((array) $attribute, $this->getValue(null)));
    }
}

Пример выше - стандартное поведение TimestampBehavior из состава Yii2. Это поведение добавляет автоматическое заполнение полей created_at и updated_at при сохранении или изменении объектов ActiveRecord или унаследованных от ActiveRecord.

Разберем свойства и методы этого класса:

  • $createdAtAttribute это имя свойства ActiveRecord, которое задается при создании записи в СУБД.
  • $updatedAtAttribute - стандартное имя свойства, которое заполняется при обновлении записи в СУБД.
  • $value - значение, которое используется для сохранении. По умолчанию значение времени, полученное через функцию time()
  • init - инициализирует обработку событий
  • getValue - возвращает $value или time()
  • touch - аналог POSIX-команды touch, которая "касается", т. е. обновляет время обновления записи.

Определять включаемые в основной объект свойства можно слеюущим образом:

class someBehavior
    public $publicProperty; // свойство автоматически окажется в расширяемом объекте
    private $getterSetterProperty; //свойство, как приватное, не доступно снаружи, однако доступно через геттеры и сеттеры:

    public function getHiddenProperty(){
        return $this->getterSetterProperty;
    }

    public function setHiddenProperty($value){
        $this->getterSetterProperty = $value;
    }

    public function funcFromBehavior(){ //публичная функция

    }

События

Для обработки событий основного объекта нужно переопределить метод events:

class someBehavior {
    ...
    public function events(){
        return [
            ActiveRecord::EVENT_BEFORE_DELETE => 'beforeDelete'
        ]
    }

    public function beforeDelete($event){
        //...
    }
}

В конфигурации, указанной выше в events, при удалении будет вызван метод beforeDelete, который, например, может реализовывать каскадное удаление или удаление файлов на диске, связанных с записью (например, если запись о изображении, удалять файлы изображения разных размеров)

Прикрепление событий

Для прикрепления в основном объекте задается метод behaviors, в котором указывается конфигурации в массиве с используемыми поведениями:

class Img extends ActiveRecord
{
    public function behaviors()
    {
        return [
            someBehavior::className(),

            [
                'class' => someBehavior::className(),
                'publicProperty' => 15,
                'hiddenProperty' => 100500
            ]
        ]
    }
}

Так же можно задавать имена поведениям через ключи массива.

attachBehavior и detachBehavior

Эти две функции позволяют подключать и отключать поведения "на горячую".

Использование поведений

После подключения, публичные свойства, свойства, определенные через геттеры и сеттеры, а так же публичные методы становятся доступы в основном объекте.

echo $someObjectWithBehavior->hiddenProperty;
$someObjectWithBehavior->funcFromBehavior();

Плюсы и минусы

Это как трейты. но не трейты :-)