Router :: extensions['json']对ErrorController无效

问题描述

我的目标是在请求时(通过标头和/或文件扩展名)将异常消息转换为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错误消息?

相关代码

  • config/routes.PHP

      <?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();
    
    

解决方法

  1. 在相应范围内使用setExtensions()而不是全局调用
  2. 如果使用前缀,请配置确切的前缀
  3. 清除缓存: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返回。