Выполните мой код перед любым действием любого контроллера

Я хотел бы проверить, заполнил ли мой пользователь определенные поля в своем профиле, прежде чем он сможет получить доступ к любому действию любого контроллера. Например

if(empty(field1) && empty(field2))
{
   header("Location:/site/error")
}

В yii1 я мог бы сделать это в protected\components\Controller.php в функции init() Но в yii2 я не уверен, куда поместить мой код. Я не могу изменять основные файлы, но не уверен, что делать в backend моего расширенного приложения, чтобы заставить его работать.

Я знаю, что могу использовать user beforeAction(), но у меня слишком много контроллеров для этого и для отслеживания каждого контроллера.

Ответ 1

Если вам нужно выполнить код перед каждым контроллером и действием, вы можете сделать следующее:

1. Добавьте компонент в каталог компонентов, например (MyGlobalClass):

namespace app\components;
class MyGlobalClass extends \yii\base\Component{
    public function init() {
        echo "Hi";
        parent::init();
    }
}

2. Добавьте компонент MyGlobalClass в свой массив компонентов в файле конфигурации:

'components' => [
    'MyGlobalClass'=>[
        'class'=>'app\components\MyGlobalClass'
     ],
     //other components

3 - добавьте MyGlobalClass в массив bootstarp в файле конфигурации:

'bootstrap' => ['log','MyGlobalClass'],

Теперь вы можете видеть Hi перед каждым действием.

Обратите внимание, что если вам не нужно использовать Events и Behaviors, вы можете использовать \yii\base\Object вместо \yii\base\Component

Ответ 2

Создайте новый контроллер   

namespace backend\components;
class Controller extends \yii\web\Controller {
    public function beforeAction($event)
    {
        ..............
        return parent::beforeAction($event);
    }
}

Все ваши контроллеры должны теперь расширить бэкэнд \components\Controller, а не \yii\web\Controller. с этим вы должны изменить каждый контроллер. Я бы пошел на это решение.

Я считаю, что вы также можете заменить 1 класс другим (поэтому никаких изменений в любом контроллере не требуется), что-то вроде

\Yii::$classMap = array_merge(\Yii::$classMap,[
                '\yii\web\Controller'=>'backend\components\Controller',
            ]);

Подробнее см.: http://www.yiiframework.com/doc-2.0/guide-tutorial-yii-integration.html, и я взял код здесь: https://github.com/mithun12000/adminUI/blob/master/src/AdminUiBootstrap.php

вы можете поместить это в свой файл index.php. Однако убедитесь, что вы очень хорошо документируете это изменение, так как кто-то, кто придет и попытается отладить ваш код, будет полностью смущен этим.

Ответ 3

Просто добавьте конфигурационный файл в $config array:

    'on beforeAction' => function ($event) {
           echo "Hello";
    },

Ответ 4

Или, https://github.com/yiisoft/yii2/blob/master/docs/guide/security-authorization.md использовать RBAC, чтобы ограничить доступ к действиям контроллеров по одному по правилам. Почему вы хотите ограничить доступ к действиям контроллера, основанным на пользовательских полях, вне меня. Вы не сможете получить доступ к чему-либо (включая регистрационную форму), если вы разместите там ограничение.