根据数据库结果设置Yii2 catchAll路由

时间:2015-03-10 22:21:04

标签: php routes yii2

<?php

namespace app\modules\site\controllers;

use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use app\models\SiteSettings;

class CommonController extends Controller {

public function init() {
    Yii::$app->language = 'bg-BG';
    Yii::$app->formatter->locale = 'bg-BG';
    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];
    }
}

}

我尝试在CommonController init方法中设置catchAll路由,但它会抛出一个错误:

  

从空值创建默认对象

是否可以根据数据库提供的条件设置catchAll路由?

2 个答案:

答案 0 :(得分:3)

您需要在处理请求之前设置catchAll属性。重新启动控制器后执行Init方法,因此不会产生任何影响。您需要使用应用程序onBeforeRequest事件来设置catchAll路由。

在配置文件集中:

$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' = [
        ....
    ]
];

您可以通过缓存SiteSettings :: find() - &gt; one();避免为每个请求打开与数据库的连接。

<强>更新 我不确定catchAll是否可用于特定模块,但您可以处理onBeforeAction事件并重定向到自定义路由。

'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']);
    }
},

答案 1 :(得分:0)

以下是我的维护模式解决方案,仅适用于指定的 yii2模块

  • 你必须创建一个普通的动作,它将用作模块的任何控制器的维护模式动作,你需要哪种维护模式
  • 您需要创建简单的视图布局和带有用于维护操作的视图页面标记的文件
  • 您需要向目标yii2的beforeAction方法添加一些代码 模块

因此,您的维护操作可能如下所示:

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');
}

,您的beforeAction方法可能如下所示:

// 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;
}

我认为你可以将它用于几个yii2模块。