我正在尝试在Yii2
控制器中执行一些代码,因为我需要模型中的一些代码可以在behaviors
部分中访问,所以我可以将模型作为参数传递并避免运行重复查询;但是我也需要能够找出被叫action
的内容,但我没有太多运气。
我已尝试使用beforeAction
,但似乎运行 AFTER behaviours
代码,这对我没用。
然后我尝试使用init
,但此时似乎无法通过action
提供$this->action->id
。
一些示例代码:
class MyController extends Controller {
public $defaultAction = 'view';
public function init() {
// $this->action not available in here
}
public function beforeAction() {
// This is of no use as this runs *after* the 'behaviors' method
}
public function behaviors() {
return [
'access' => [
'class' => NewAccessControl::className(),
'only' => ['view','example1','example2'],
'rules' => [
[
'allow' => false,
'authManager' => [
'model' => $this->model,
'other_param' => $foo,
'other_param' => $bar,
],
'actions' => ['view'],
],
// everything else is denied
],
],
];
}
public function viewAction() {
// This is how it is currently instantiated, but we want to instantiate *before* the behavior code is run so we don't need to instantiate it twice
// but to be able to do that we need to know the action so we can pass in the correct scenario
$model = new exampleModel(['scenario' => 'view']);
}
}
authManager
只是对member variable
类扩展中AccessRule
的引用。
无论如何我能做到吗?
答案 0 :(得分:9)
好吧,如果我找对你,你正在寻找这样的东西:
public function behaviors()
{
$model = MyModel::find()->someQuery();
$action = Yii::$app->controller->action->id;
return [
'someBehavior' => [
'class' => 'behavior/namespace/class',
'callback' => function() use ($model, $action) {
//some logic here
}
]
];
}
因为behaviors()
只是一个方法,你可以声明任何变量并添加你想要的任何逻辑,你必须遵循的唯一约定 - 返回类型必须是数组< / em>的。
如果您使用自定义行为,则可以使用events()
方法,将行为方法绑定到某些事件。 E.g。
class MyBehavior extends Behavior
{
public function events()
{
return [
\yii\web\User::EVENT_AFTER_LOGIN => 'myAfterLoginEvent',
];
}
public function myAfterLoginEvent($event)
{
//dealing with event
}
}
在此示例中,myAfterLoginEvent
将在用户成功登录到应用程序后执行。 $event
变量将由框架传递,根据事件类型,它将包含不同的数据。阅读about event object
<强>更新强>
正如我现在所看到的,我的答案对于事件和行为更为通用。现在,当您添加代码时,我建议您使用以下代码覆盖行为&#39> beforeAction($action)
方法:
public function beforeAction($action)
{
$actionID = $action->id;
/* @var $rule AccessRule */
foreach ($this->rules as &$rule) {
$model = &$rule->authManager['model'];
//now set model scenario maybe like this
$model->scenario = $actionID;
}
//now call parent implementation
parent::beforeAction($action);
}
另请参阅 AccessControl implementation of beforeAction
方法,它会调用每个规则allows
方法,并将当前操作作为参数传递给它。因此,如果您有扩展 AccessRule 的类,您可以覆盖允许($ action,$ user,$ request)方法或matchCustom($action)
方法来设置适当的模型场景。希望这会有所帮助。
还有一个选择:
覆盖控制器的runAction($id, $params = [])
方法。这里$ id是 actionID - 正是您所需要的。检查ID,设置适当的模型方案并调用parent::runAction($id, $params);