Получение действия контроллера до того, как код поведения будет запущен в Yii2

Я пытаюсь выполнить некоторый код внутри контроллера Yii2 как мне нужен какой-то код из модели, чтобы быть доступным в разделе behaviors чтобы я мог передать модель в качестве параметра и не запускать повторяющиеся запросы; однако мне также нужно выяснить, какое action вызывается, но мне не очень повезло.

Я пробовал использовать beforeAction но кажется, что это запускается ПОСЛЕ выполнения кода 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 .

В любом случае я могу это сделать?

Хорошо, если я получу вас правильно, вы ищете что-то вроде этого:

 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() – это всего лишь метод, вы можете объявлять любые переменные и добавлять любую логику, которая вам нужна, единственное соглашение, которое вы должны следовать, – это то, что возвращаемый тип должен быть массивом .

Если вы используете свое обычное поведение, вы можете использовать метод events() где вы можете привязать методы вашего поведения к определенным событиям. Например

 class MyBehavior extends Behavior { public function events() { return [ \yii\web\User::EVENT_AFTER_LOGIN => 'myAfterLoginEvent', ]; } public function myAfterLoginEvent($event) { //dealing with event } } 

В этом примере myAfterLoginEvent будет выполнен после успешного входа пользователя в приложение. переменная $event будет передана каркасом и в зависимости от типа события будет содержать разные данные. Читайте о объекте события

ОБНОВИТЬ:

Как я теперь вижу, мой ответ был более общим по поводу событий и поведения. И теперь, когда вы добавили код, я могу предложить вам переопределить beforeAction($action) поведения 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); } 

Также взгляните на реализацию beforeAction метода beforeAction , который он вызывает для каждого правила, allows метод с передачей текущего действия ему в качестве параметра. Поэтому, если у вас есть класс, который расширяет AccessRule , вы можете либо переопределить метод ($ action, $ user, $ request), либо метод matchCustom($action) для установки соответствующего модельного сценария. Надеюсь, это поможет.

Еще одна альтернатива:

переопределить runAction($id, $params = []) контроллера runAction($id, $params = []) . Здесь $ id – actionID – именно то, что вам нужно. Проверьте идентификатор, установите соответствующий сценарий модели и вызовите parent::runAction($id, $params);