动态设置错误动作的布局文件 [英] Set the layout file for error action dynamically

查看:148
本文介绍了动态设置错误动作的布局文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道有不同的方式来选择布局文件。可以在配置
  • Yii ::




    • $ app-> layout ='...'

    • Controller :: $ layout / li>


    我有一些控制器使用不同的布局文件,如下所示:

      class FirstController extends yii\web\Controller {
    public $ layout ='firstLayout';
    ...
    }

    class SecondController extends yii\web\Controller {
    public $ layout ='secondLayout';
    ...
    }

    现在我有错误处理是默认的在Yii2。因此,配置设置将'errorHandler'设置为'site / error'(这是一个全局错误处理程序)。还有一个SiteController与

      class SiteController extends yii\web\Controller {
    public function actions() {
    return [
    'error'=> [
    'class'=> 'yii\web\ErrorAction',
    ],
    ];
    }
    ...
    }

    我的问题是错误处理程序默认使用SiteController的布局文件。但它应该是实际调用的控制器。如何实现这个动态?

    解决方案

    可以在应用程序事件中设置: p>

      $ config = [
    'id'=> 'my-app',
    'basePath'=> dirname(__ DIR__),
    'params'=> ...
    'bootstrap'=> ['log'],
    'components'=> [
    ...
    'errorHandler'=> [
    'errorAction'=> 'site / error',
    ],
    ...
    ],

    'on beforeAction'=> function(yii\base\ActionEvent $ e){
    if($ e-> action-> id ==='error'&& $ e-> action-> > id ==='site'){
    //这是第二步
    if(isset(Yii :: $ app-> params ['requested-layout']))
    $ e-> action-> controller-> layout = Yii :: $ app-> params ['requested-layout'];
    } else {
    //这首先发生
    Yii :: $ app-> params ['requested-layout'] = $ e-> action-> controller->布局;
    }
    },
    ];会发生什么:请注意,如果在操作中抛出异常,则beforeAction将被调用两次。第二次调用是由错误处理程序引起的。现在,在每个需求请求下,当前的布局被存储在某个地方(我使用全局可用的 Yii params 为此)。如果由于某种原因,错误处理程序需要被调用为包含错误的布局文件动作控制器被采纳到存储的布局文件。



    开放问题:




    • 模块不被考虑。需要更多的逻辑。

    • 'onAction' 被调用和 Yii :: $ app-> params ['requested-layout'] 将仅针对现有操作和控制器(和模块)和在操作方法中抛出的异常设置。

    • 如果路由是无效或另一个错误发生beforeAction处理程序将被直接调用站点/错误 而不执行。所以布局文件没有得到采用(可以通过beforeRequest''的实现解决),并且将使用默认布局(可以是真正的默认或可以设置以不同的方式(例如SiteController的$ layout属性)。

    • 如果布局文件不在一个文件夹中(在 Application :: $ layoutFiles / a>)。



    我认为扩展此行(未测试)可以轻松考虑该模块:

      Yii :: $ app-> params ['requested-layout'] = $ e-> action-> controller-> ;布局?:
    $ this-> action-> controller-> module-> layout;

    让我知道这是有道理还是错误。


    I know there are different ways to choose layout file. It can be done

    • in the configuration
    • with Yii::$app->layout = '...'
    • with Controller::$layout

    I have some controllers that use different layout file like this:

    class FirstController extends yii\web\Controller {
        public $layout = 'firstLayout';
        ...
    }
    
    class SecondController extends yii\web\Controller {
        public $layout = 'secondLayout';
        ...
    }
    

    Now I have the error handling that is default in Yii2. So there is the configuration setting which sets 'errorHandler' to 'site/error' (which is a global error handler). And there is the SiteController with

    class SiteController extends yii\web\Controller {
        public function actions() {
            return [
                'error'   => [
                    'class' => 'yii\web\ErrorAction',
                ],
            ];
        }
        ...
    }
    

    My problem is that the error handler uses the layout file of the SiteController by default. But it should be the one from the controller that was actually called. How could I achieve this dynamically?

    解决方案

    It could be set in an application event:

    $config = [
        'id'              => 'my-app',
        'basePath'        => dirname(__DIR__),
        'params'          => ...
        'bootstrap'       => ['log'],
        'components'      => [
            ...
            'errorHandler' => [
                'errorAction' => 'site/error',
            ],
            ...
        ],
    
        'on beforeAction' => function (yii\base\ActionEvent $e) {
            if ($e->action->id === 'error' && $e->action->controller->id === 'site') {
                // this is the second step
                if (isset(Yii::$app->params['requested-layout']))
                    $e->action->controller->layout = Yii::$app->params['requested-layout'];
            } else {
                // this happens first
                Yii::$app->params['requested-layout'] = $e->action->controller->layout;
            }
        },
    ];
    

    What happens: Note that beforeAction gets called twice if an exception gets thrown in an action. The second call is caused by the error handler. Now, on each reqular request the current layout gets stored somewhere (I used the globally available Yii params for this). If then for some reason the error handler needs to be called the layout file for the containing error action controller gets adopted to the stored layout file.

    Open issues:

    • Modules are not taken into account. Would require some more logic.
    • 'on beforeAction' gets called and Yii::$app->params['requested-layout'] will be set only for existing actions and controllers (and modules) and exceptions that gets thrown within action methods.
    • If the route is invalid or another error occurres the beforeAction handler will be called directly for site/error without executing it before. So the layout file does not gets adopted (could be solved with an implementation for 'on beforeRequest') and the default layout will be used (can be really default or could be set in different ways (e.g. $layout property of the SiteController).
    • More logic could be required if the layout files are not in one single folder (defined in Application::$layoutFiles).

    I think the module could be considered as well easily with extending this line (not tested):

    Yii::$app->params['requested-layout'] = $e->action->controller->layout ?: 
                                            $this->action->controller->module->layout;
    

    Let me know if this makes sense or is wrong.

    这篇关于动态设置错误动作的布局文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆