有没有办法在未构造的 Class 中使用 CakeResponse Object?

Is there a way of using CakeResponse Object in unconstructed Class?

我目前正在为 CakePHP 中的应用程序自定义 ErrorHandler。 原因?嗯,机器人总是试图在您的服务器中查找内容,有时它们会引发异常和/或错误。

这个 ErrorHandler 的想法是过滤请求并用适当的 headers 响应并通过处理此类请求防止进一步的请求损坏并使其透明用户客户端 (因为它可能会影响 JavaScript).


And what better way than to use the Framework's functionality, right?

The thing is that since this ErrorHandler is being used statically, well, there is no constructor so nothing inherits anything, it doesn't matter if you instantiate any other CakePHP Object.

What would be the appropriate way to use CakeResponse Object?


CakePHP 的配置:

app/Config/bootstrap.php:

App::uses('CustomErrorHandler', 'Lib');

app/Config/core.php:

// Error and exception handlers.
Configure::write('Error', array(
    'handler' => 'CustomErrorHandler::handleError',
    'level' => E_ALL & ~E_DEPRECATED,
    'trace' => true
));
Configure::write('Exception', array(
    'handler' => 'CustomErrorHandler::handleException',
    'renderer' => 'ExceptionRenderer',
    'log' => true
));

app/Lib/CustomErrorHandler.php:

  ... rest of class code ...

  /**
   * Named after convention: This method receives all CakePHP's
   * errors and exceptions…
   *
   * @param  array $e The exception object.
   * @return mixed    Returns the error handling or header redirection.
   */
   public static function handleException($e)
   {
       $message = (string) $e->getMessage();
       $code    = (int)    $e->getCode();
       $file    = (string) $e->getFile();
       $line    = (string) $e->getLine();

       // If it's a Blacklist resource exception it will log it and redirect to home.
       if (self::__isResourceException($message))
       {
           return self::__dismissError();
       }

       return parent::handleException($e);
   }

  /**
   * This method redirects to home address using CakeResponse Object.
   *
   * @return mixed
   */
   private static function __dismissError()
   {
       return (new CakeResponse)->header(array(
           'Location' => self::$redirectUrl
       ));
   }
}

更新 2:

将在 ExceptionRenderer 上尝试一个小层。

在那里使用 CakeResponse object 并没有什么意义...如果你调用 send() 它会起作用,但是只有那个 header,与直接使用 header() 相比没有任何优势。

话虽这么说,但无论如何您都放弃了 Controller.shutdownDispatcher.afterDispatch 事件。它们在 ExceptionRenderer::_shutdown() 中被调度,并且通常用于设置响应 headers(与 CORS 相关的 headers 是一个很好的例子),所以你应该考虑是否可以删除它们,甚至可能是必需的。

如果您需要保留 shutdownafterDispatch 事件,那么您应该自己触发它们,或者甚至可以使用处理该特定类型的扩展 ExceptionRenderer异常并发送一个空响应,其中添加了您的位置 header。

另见