我想做一些与 this 非常相似的事情但在 CakePHP 世界中用于 AJAX 请求。目前我正在这样做:
$this->autoRender = false;
$this->response->statusCode(500);
它基于 this .但是,此解决方案不允许我像 Rails 示例中那样包含自定义消息,因此,在我的客户端错误处理程序中,我可以显示包含在 500 错误响应中的消息。
我如何在 CakePHP 中实现与 Ruby on Rails 示例相同的功能?
最佳答案
如上所述,异常是在 CakePHP 中返回 AJAX 请求错误的方式。这是我的解决方案,用于更好地控制错误的外观。另外,如上所述,我使用的是自定义异常渲染器,但不是自定义异常。默认的错误响应是一个像这样的 JSON 对象:
{"name":"An Internal Error Has Occurred", "url": "\/users\/login.json"}
我几乎喜欢默认渲染器处理 AJAX 错误的方式;我只想稍微调整一下:
<?php
// File: /app/Lib/Error/CustomExceptionRenderer.php
App::uses('ExceptionRenderer', 'Error');
class CustomExceptionRenderer extends ExceptionRenderer {
// override
public function error400($error) {
$this->_prepareView($error, 'Not Found');
$this->controller->response->statusCode($error->getCode());
$this->_outputMessage('error400');
}
// override
public function error500($error) {
$this->_prepareView($error, 'An Internal Error Has Ocurred.');
$code = ($error->getCode() > 500 && $error->getCode() < 506) ? $error->getCode() : 500;
$this->controller->response->statusCode($code);
$this->_outputMessage('error500');
}
private function _prepareView($error, $genericMessage) {
$message = $error->getMessage();
if(!Configure::read('debug') && !Configure::read('detailed_exceptions')) {
$message = __d('cake', $genericMessage);
}
$url = $this->controller->request->here();
$renderVars = array(
'name' => h($message),
'url' => h($url),
);
if(isset($this->controller->viewVars['csrf_token'])) {
$renderVars['csrf_token'] = $this->controller->viewVars['csrf_token'];
}
$renderVars['_serialize'] = array_keys($renderVars);
$this->controller->set($renderVars);
}
}
然后,在 bootstrap.php 中:
Configure::write('Exception.renderer', 'CustomExceptionRenderer');
下面是它的工作原理:
- 假设我想在我的错误响应中返回一个新的 CSRF token ,这样如果我现有的 token 在异常被抛出之前已经过期,我下次尝试请求时就不会被黑洞。查看Security Component documentation有关 CSRF 保护的更多信息。
- 在 app/Lib/Error 中创建一个新类。您可以扩展默认渲染器,也可以不扩展。由于我只想更改一些小东西,并使示例保持简单,因此我对其进行了扩展。
- 覆盖默认呈现器用于创建将返回的 JSON 对象的方法。这是通过 Request Handler Component 完成的,并符合最佳实践。事实上,默认渲染器做同样的事情。
- 新的私有(private)方法让事情保持干爽。
- 我对在生产中没有收到自定义错误消息的问题的解决方案是添加一个可选的配置键。默认情况下,此类将在生产中显示通用消息,但如果您将调试设置为 0,并且您想要特定的错误消息:
Configure::write('detailed_exceptions', 1);
< - 将新 token 添加到响应中(如果存在)。就我而言,我已经在 AppController 的 beforeFilter 方法中对新 token 调用了
Controller::set
,因此它在$this->controller->viewVars
中可用.可能有许多其他方法可以实现此目的。
现在您的响应如下所示:
{
"name":"The request has been black-holed",
"url":"\/users\/login.json",
"csrf_token":"1279f22f9148b6ff30467abaa06d83491c38e940"
}
任何类型的任何附加数据都可以添加到传递给 Controller::set
的数组中以获得相同的结果。
关于php - CakePHP 中的 Ajax 错误处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11585620/