Set Yii2 catchAll route depending on database result

佐手、 提交于 2019-12-04 15:24:31

You need to setup catchAll property just before request is handled. Init method is executed after resloving controller, so it won't have any effect. You need to use application onBeforeRequest event to setup up catchAll route.

In config file set following:

$config = [
    'id' => '...',
     ......

    'on beforeRequest' => function () {
        Yii::$app->params['siteSettings'] = SiteSettings::find()->one();            
        if (Yii::$app->params['siteSettings']->in_maintenance == 1) {
            Yii::$app->catchAll = [
              'index/maintenance', 
              'message' => Yii::$app->params['siteSettings']->maintenance_message
            ];
        }
    },
    ....
    'comonents' = [
        ....
    ]
];

You can add little improvement to this by caching SiteSettings::find()->one(); to avoid opening connection to database for every request.

Update: I am not sure if catchAll can be used for specific module, but you can handle onBeforeAction event and redirect to custom route.

'on beforeAction' => function ($event) {

    $actionId = $event->action->id;
    $controllerId = $event->action->controller->id;
    $moduleId = $event->action->controller->module->id;

    //TODO: Check module here
    if (!(($controllerId == "site") && ($actionId == "offline")))
    {
        return Yii::$app->response->redirect(['site/offline']);
    }
},

Here is my solution for maintenance mode only for specified yii2 module(s):

  • you have to create an ordinary action which will be used as a maintenance mode action for any controller of the module which maintenance mode you need for
  • you need to create simple view layout and a file with view page markup for maintenance action
  • you need to add some code to beforeAction method of your target yii2 module

So your maintenance action can looks like this:

public function actionMaintenance()
{
    // Usually for maintenance mode websites use different simplified layout
    // than for normal pages (without any menus and other stuff)
    $this->layout = 'maintenance_layout';
    return $this->render('maintenance_page');
}

and your beforeAction method can looks like this:

// You can use beforeAction handler inside any yii2 module
public function beforeAction($action)
{
    // default handling of parent before action
    if(!parent::beforeAction($action)) {
        return false;
    }

    // Retrieving of maintenance setting from DB 
    // (of course, you can use smth. other)
    $onMaintenance = Settings::find()->where([
        'name' => 'maintainance_mode'
    ])->asArray()->one();

    // It the module have to be in maintenance mode according to our settings
    if($onMaintenance['value'] === 'on') {
        // and currently requested action is not our maintenance action
        // this is used to avoid infinite call loop 
        if($action->id != 'maintenance')
            // we redirect users to maintenance page
            \Yii::$app->response->redirect(['/frontend/site/maintenance']);
        else
            // and we allow an action to be executed if it is our maintenance action
            return true;
    }

        return true;
}

I think you can use this for several yii2 modules.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!