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


Attach behavior globally for all models in application config (without inheritance)

我正在处理 Yii2 在添加时间戳行为以从主配置运行时的问题。原因是我必须在大多数模型的前端和后端使用它。

在模型中使用它很简单:

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'); } ,
],

但它不起作用。有什么想法吗?

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

它背后的基本思想是使用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继承的所有模型,然后再将其保存到数据库。

您也可以省略createdAtAttributeupdatedAtAttribute,因为它们默认情况下已经具有这些名称(因为它是最常见的)。

如您所见,仅当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  
    }
}

然后你需要把它包含在引导部分的配置中:

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

官方文档:

  • 事件::on()
  • 引导接口

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

我没有找到在那里指定ActiveRecord的方法。

您可以看到这个问题,但是那里的行为附加到整个应用程序,这可以通过配置来实现。

我知道

这是一个有点老的问题,但如果有人遇到同样的问题,我将分享我发现的干净方法。我只是在特质中定义一种行为。然后我只是在模型中使用该特征,仅此而已。它在模型中只增加了一行,但它更干净,使代码维护变得轻而易举。

这是示例特征

<?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
}