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:
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:
'on beforeAction'
gets called andYii::$app->params['requested-layout']
will be set only for existing actions and controllers (and modules) and exceptions that gets thrown within action methods.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).Application::$layoutFiles
).I think the module could be considered as well easily with extending this line (not tested):
Let me know if this makes sense or is wrong.
One way could be to set the the layout file for the application in
beforeAction
in each controller:It could be optimized by putting this in an extra controller from which all other controllers inherit.
But I don't really like this solution. Seems to me like a workaround. Also this does not work if the SiteController defines a layout by itself (as
$layout
property or within a method).