在应用程序配置中为所有模型全局附加行为(无继承)

cku*_*014 8 php behavior yii2

我正在处理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'); } ,
        ],
    ];
}
Run Code Online (Sandbox Code Playgroud)

但如果我试图在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'); } ,
],
Run Code Online (Sandbox Code Playgroud)

但它不起作用.有任何想法吗?

aro*_*hev 11

如果您不想使用继承,我可以建议以下方法.

它背后的基本思想是使用以下事件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');
                },
            ]);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

此代码将动态附加TimestampBehavior到从yii\db\ActiveRecord将其保存到数据库之前继承的所有模型.

您也可以省略createdAtAttribute,updatedAtAttribute因为默认情况下它们已经有了这些名称(因为它最常见).

正如您所看到的,只有当两者created_atupdated_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  
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你需要在bootstrap部分的config中包含它:

return [
    'bootstrap' => [
        'common\components\EventBootstrap',
    ],
];
Run Code Online (Sandbox Code Playgroud)

官方文件:

附加说明:我也尝试仅通过应用程序配置指定它,但没有成功.

我没有找到指明ActiveRecord那里的方法.

您可以看到这个问题,但是通过配置可以将整个应用程序附加到该行为.