Подключите поведение глобально для всех моделей в конфигурации приложения (без наследования)

Я имею дело с проблемой для Yii2 при добавлении TimestampBehavior для запуска из основной конфигурации. Причина в том, что я должен использовать его во внешнем интерфейсе и бэкэнде на большинстве моих моделей.

Использовать его в модели просто:

public function behaviors()
{
return [
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'value' => function(){ return date('Y-m-d H:i:s'); } ,
],
];
}

Но если я пытаюсь добавить поведение в main.php, ничего не происходит.
Я думал о:

'as timestamp'=>[
'class'=> \yii\behaviors\TimestampBehavior::className(),
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'value' => function(){ return date('Y-m-d H:i:s'); } ,
],

Но это не работает. Есть идеи?

7

Решение

Если вы не хотите использовать наследование, я могу предложить следующий метод.

Основная идея заключается в использовании событий ActiveRecord:

use yii\base\Event;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;

...

$events = [ActiveRecord::EVENT_BEFORE_INSERT, ActiveRecord::EVENT_BEFORE_UPDATE];

foreach ($events as $eventName) {
Event::on(ActiveRecord::className(), $eventName, function ($event) {
$model = $event->sender;

if ($model->hasAttribute('created_at') && $model->hasAttribute('updated_at')) {
$model->attachBehavior('timestamp', [
'class' => TimestampBehavior::className(),
'value' => function () {
return date('Y-m-d H:i:s');
},
]);
}
});
}

Этот код будет динамически прикрепляться TimestampBehavior для всех моделей, которые унаследованы от yii\db\ActiveRecord перед сохранением в базу данных.

Вы также можете опустить createdAtAttribute а также updatedAtAttribute потому что они уже имеют эти имена по умолчанию (так как это наиболее часто встречается).

Как видите, поведение привязано только тогда, когда оба created_at а также updated_at атрибуты существуют, для этого не нужно создавать расширенное поведение.

Чтобы избежать наследования и копирования / вставки, этот код должен запускаться при каждой загрузке приложения.

Вы можете сразу добавить это в сценарий ввода (перед запуском приложения), и он будет работать, но не рекомендуется размещать его здесь, также эти файлы генерируются автоматически и в списке игнорируемых файлов git.

Поэтому вам нужно создать только один отдельный компонент, содержащий эту логику, и включить его в конфигурацию. Нет необходимости расширять классы и т. Д.

Допустим, это называется common\components\EventBootstrap, Он должен реализовать BootstrapInterface для того, чтобы работать правильно.

namespace common\components;

// Other namespaces from previous code

use yii\base\BootstrapInterface;

class EventBootstrap implements BootstrapInterface
{
public function bootstrap($app)
{
// Put the code above here
}
}

Затем вам нужно включить его в config в разделе начальной загрузки:

return [
'bootstrap' => [
'common\components\EventBootstrap',
],
];

Официальная документация:

Дополнительные примечания: Я также пытался указать это только через конфигурацию приложения, но безуспешно.

Я не нашел способ указать ActiveRecord там.

Ты можешь видеть этот вопрос, но поведение там привязано ко всему приложению, что возможно через config.

10

Другие решения

Я знаю, что это немного старый вопрос, но если у кого-то возникла такая же проблема, я поделюсь тем, что нашел, как чистым способом сделать это. Я просто определяю поведение по признаку. Затем я просто использую эту черту в моделях, вот и все. Он добавляет только одну строчку в модель, но все же чище и делает обслуживание кода немного проще.

Вот примерная черта

<?php

namespace common\traits;

use Yii;
use yii\behaviors\BlameableBehavior;
use yii\behaviors\TimestampBehavior;

trait Signature
{

public function behaviors()
{
return [
[
'class' => BlameableBehavior::className(),
'createdByAttribute' => 'created_by',
'updatedByAttribute' => 'updated_by',
],
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'value' =>function(){
return time();
},
],
];
}
}

И код модели

class Category extends \yii\db\ActiveRecord
{
use \common\traits\Signature;
// Model code here
}
2

По вопросам рекламы [email protected]