Yii2:将行为附加到每个控制器
Yii2: Attach behavior to every controller
我们如何将行为附加到应用程序中的所有 Web 控制器?
我知道这 理论上 可以通过依赖注入实现,所以我假设这样的事情会起作用:
Yii::$container->set('yii\web\Controller', [
'as myBehavior' => [
'class' => 'app\behaviors\MyBehavior',
],
]);
但是 DI 需要精确的 class 匹配(附加到父 class 将不起作用)。无法提前知道所有控制器名称,尤其是当大多数控制器名称来自 3rd 方模块时。
还有其他方法吗?
编辑:这样做的目的是动态添加控制器过滤器(这只是一种特殊类型的行为)。因此,在 EVENT_BEFORE_ACTION
事件期间附加行为是不够的,因为它是在请求过滤后很久才触发的。
有趣的问题,我必须说。我找不到简单的解决方案,但我有这个老掉牙的想法。您可以利用 Yii 自动加载器并加载您的 yii\web\Controller
版本而不是原始版本。
为此:
从供应商处复制原始文件并将其放入您的应用程序
不要更改原来的命名空间和名称。
在里面添加你的行为配置(或者只是行为的代码,随便什么)。
将此行添加到每次应用程序运行时都会调用的位置(如入口点文件或 bootstrap 文件,必须在 after vendor/yiisoft/yii2/Yii.php
文件是 required
):
Yii::$classMap['yii\web\Controller'] = ''; // replace '' with the path to your version
// of yii\web\Controller
现在,每次自动加载器尝试加载 yii\web\Controller
时,它都会加载您的版本,因此它应该可以像您希望的那样工作。
这样做的明显弊端是升级 Yii 时您必须手动检查原始文件是否未更新以使其保持最新。
模块(和应用程序)的 beforeAction
事件在该事件的控制器版本之前触发。您可以利用它并将行为附加到当前控制器。
例如在您的 web.php 配置中:
return [
'on beforeAction' => function() {
Yii::$app->controller->attachBehavior(
'myBehavior',
\app\behaviors\MyBehavior::class
);
},
// ... other configurations
];
当然缺点是从一开始就没有附加行为
注意:如果您的目标是将过滤器附加到每个控制器,您可以简单地将它附加到应用程序本身而不是控制器。
子控制器行为取决于 AccesControler 行为
class WorkerimgController extends OfficeController{
public function behaviors()
{
return ArrayHelper::merge(parent::behaviors(), [
]);
}
}
我们如何将行为附加到应用程序中的所有 Web 控制器?
我知道这 理论上 可以通过依赖注入实现,所以我假设这样的事情会起作用:
Yii::$container->set('yii\web\Controller', [
'as myBehavior' => [
'class' => 'app\behaviors\MyBehavior',
],
]);
但是 DI 需要精确的 class 匹配(附加到父 class 将不起作用)。无法提前知道所有控制器名称,尤其是当大多数控制器名称来自 3rd 方模块时。
还有其他方法吗?
编辑:这样做的目的是动态添加控制器过滤器(这只是一种特殊类型的行为)。因此,在 EVENT_BEFORE_ACTION
事件期间附加行为是不够的,因为它是在请求过滤后很久才触发的。
有趣的问题,我必须说。我找不到简单的解决方案,但我有这个老掉牙的想法。您可以利用 Yii 自动加载器并加载您的 yii\web\Controller
版本而不是原始版本。
为此:
从供应商处复制原始文件并将其放入您的应用程序
不要更改原来的命名空间和名称。
在里面添加你的行为配置(或者只是行为的代码,随便什么)。
将此行添加到每次应用程序运行时都会调用的位置(如入口点文件或 bootstrap 文件,必须在 after
vendor/yiisoft/yii2/Yii.php
文件是required
):Yii::$classMap['yii\web\Controller'] = ''; // replace '' with the path to your version // of yii\web\Controller
现在,每次自动加载器尝试加载 yii\web\Controller
时,它都会加载您的版本,因此它应该可以像您希望的那样工作。
这样做的明显弊端是升级 Yii 时您必须手动检查原始文件是否未更新以使其保持最新。
模块(和应用程序)的 beforeAction
事件在该事件的控制器版本之前触发。您可以利用它并将行为附加到当前控制器。
例如在您的 web.php 配置中:
return [
'on beforeAction' => function() {
Yii::$app->controller->attachBehavior(
'myBehavior',
\app\behaviors\MyBehavior::class
);
},
// ... other configurations
];
当然缺点是从一开始就没有附加行为
注意:如果您的目标是将过滤器附加到每个控制器,您可以简单地将它附加到应用程序本身而不是控制器。
子控制器行为取决于 AccesControler 行为
class WorkerimgController extends OfficeController{
public function behaviors()
{
return ArrayHelper::merge(parent::behaviors(), [
]);
}
}