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();
Это как трейты. но не трейты :-)