Cakephp 3-抛出异常时不传输var以查看

PGB*_*GBI 1 error-handling cakephp-3.0

在我的AppController中,我定义了一个必须在我的应用程序的每个视图(包括error400.ctp,error500.ctp)中使用的变量:

// /src/Controller/AppController.php
public function beforeFilter(Event $event)
{
    parent::beforeFilter($event);
    $foo = 'bar';
    $this->set(compact('foo'));
}
Run Code Online (Sandbox Code Playgroud)

它运行良好,除了抛出异常(如NotFoundException)时:我得到以下错误:

Undefined variable: foo in /src/Template/Error/error400.ctp

这是cakephp的正常行为吗?我该如何解决?

小智 5

是的,这是正常行为,基本上是在发生什么:

  1. 引发异常(beforeFilter根据引发的位置调用异常,例如,它是为MissingAction或MissingTemplate调用的,而不是为MissingController调用的)。

  2. 请求处理被中止,并ErrorHandler介入以捕获和处理该异常。

  3. 要渲染Exception,请ErroHandler使用ExceptionRenderer,而后者又会创建special ErrorController,以替代原始控制器。这也意味着,现在您拥有完全不同的控制器来处理请求(Controller类的新实例),因此即使beforeFilter被调用$foo并被设置,它也不再有效。

  4. ExceptionRenderer将使用自己的render()方法为错误页面创建输出。

要对此进行自定义,您可以扩展default ExceptionRenderer,因此可以将变量设置为ErrorController

<?php
// goes in src/Error/AppExceptionRenderer
namespace App\Error;

use Cake\Error\ExceptionRenderer;

class AppExceptionRenderer extends ExceptionRenderer
{
    public function render()
    {
        $this->controller->set('foo', 'bar');
        return parent::render();
    }
}
Run Code Online (Sandbox Code Playgroud)

将此类设置为默认的ExceptionRenderer app.php

//...
'Error' => [
    // ...
    'exceptionRenderer' => 'App\Error\AppExceptionRenderer',
    // ...
],
Run Code Online (Sandbox Code Playgroud)

因此,您需要在两个位置设置该全局视图变量。使用模型,Configure类中的一些常用方法来读取全局变量或任何适合您的需求的方法。

有关自定义错误处理的更多信息:扩展和实现自己的异常处理程序