问题描述
我的目标是在请求时(通过标头和/或文件扩展名)将异常消息转换为JSON。根据{{3}},这需要在src/Controller/ErrorController.PHP
中发生。如果我只是将$this->RequestHandler->renderAs($this,'json')
添加到beforeFilter()
可以正常工作,但是话又说回来,我应该仅在显式请求JSON时才强制使用JSON。
-
我首先将
Router::extensions(['json'])
添加到JSON exception in cakephp 3之后的routes.PHP
顶部。 -
然后我创建了一个抛出
/foo/bar.json
的测试动作new BadRequestException('hello')
。 -
最后,在
src/Controller/ErrorController.PHP
中调试:public function beforeRender(Event $event) { parent::beforeRender($event); $this->viewbuilder()->setTemplatePath('Error'); debug($this->getRequest());exit; }
当我请求它时,我可以看到扩展名根本没有被解析:
object(Cake\Http\ServerRequest) {
[protected] params => [
'controller' => 'Foo','action' => 'bar.json',// …
'_ext' => null,]
尝试$this->getRequest()->is('json')
也会返回false
。
当我将debug(Router::extensions());exit;
添加到config/routes.PHP
的顶部时,什么也没发生。这是否意味着根本无法读取文件?还是那是因为异常在执行之前就中止了执行?
在显式请求时如何强制JSON错误消息?
相关代码:
-
<?PHP use Cake\Core\Plugin; use Cake\Routing\RouteBuilder; use Cake\Routing\Router; use Cake\Routing\Route\DashedRoute; use Cake\Http\Middleware\CsrfProtectionMiddleware; Router::extensions(['json']); debug(Router::extensions());exit; Router::defaultRouteClass(DashedRoute::class); Router::scope('/',function (RouteBuilder $routes) { $routes->registerMiddleware('csrf',new CsrfProtectionMiddleware()); $routes->applyMiddleware('csrf'); $routes->connect('/',['controller' => 'Pages','action' => 'display','home']); $routes->connect('/pages/*','action' => 'display']); $routes->fallbacks(DashedRoute::class); }); Router::prefix('abc',function ($routes) { $routes->fallbacks(DashedRoute::class); }); Router::prefix('def',function ($routes) { $routes->fallbacks(DashedRoute::class); }); Router::prefix('ghi',function ($routes) { $routes->fallbacks(DashedRoute::class); }); Router::prefix('api',function ($routes) { $routes->prefix('jkl',function ($routes) { $routes->fallbacks(DashedRoute::class); }); }); Router::prefix('mno',function ($routes) { $routes->fallbacks(DashedRoute::class); }); //Plugin::routes();
解决方法
- 在相应范围内使用
setExtensions()
而不是全局调用 - 如果使用前缀,请配置确切的前缀。
- 清除缓存:
bin/cake cache clear_all
如果操作正确,将不需要来另外配置src/Controller/ErrorController.php
like in this answer。
工作代码:
Router::prefix('myprefix',function ($routes) {
$routes->setExtensions(['json']);
$routes->fallbacks(DashedRoute::class);
});
就是这样。在.json
中具有/myprefix
扩展名的请求引发异常的操作将以JSON返回。