Установить маршрут Yii2 catchAll в зависимости от результата базы данных

<?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]; } } 

}

Я попытался установить маршрут catchAll из метода initController, но он вызывает ошибку:

Создание объекта по умолчанию из пустого значения

Можно ли установить маршрут catchAll при условии, предоставленном из базы данных?

Вам нужно настроить свойство catchAll непосредственно перед обработкой запроса. Метод Init выполняется после перенастройки контроллера, поэтому он не будет иметь никакого эффекта. Для настройки маршрута catchAll необходимо использовать приложение onBeforeRequest.

В конфигурационном файле:

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

Вот мое решение для режима обслуживания только для указанных модулей yii2 :

  • вам необходимо создать обычное действие, которое будет использоваться в качестве действия режима обслуживания для любого контроллера модуля, для которого необходим режим обслуживания
  • вам необходимо создать простой макет представления и файл с разметкой страницы просмотра для действий по обслуживанию
  • вам нужно добавить код в метод beforeAction вашего целевого модуля yii2

Таким образом, ваше действие по обслуживанию может выглядеть так:

 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.