如何在Drupal 9的JSON:API请求中添加自定义异常?
实现方案说明
使用EventSubscriber是当前场景的最优实现方案,完全符合Drupal生态的扩展规范,不会侵入核心模块代码,后续版本升级也不会产生兼容问题。
具体实现步骤
1. 创建自定义模块
新建自定义模块,假设命名为custom_jsonapi_domain_check,按Drupal规范编写custom_jsonapi_domain_check.info.yml文件即可。
2. 注册事件订阅服务
在模块根目录创建custom_jsonapi_domain_check.services.yml文件,内容如下:
services: custom_jsonapi_domain_check.domain_parameter_subscriber: class: Drupal\custom_jsonapi_domain_check\EventSubscriber\DomainParameterCheckSubscriber arguments: ['@current_route_match'] tags: - { name: event_subscriber }
3. 编写事件订阅器逻辑
在模块目录下创建src/EventSubscriber/DomainParameterCheckSubscriber.php文件,代码如下:
<?php namespace Drupal\custom_jsonapi_domain_check\EventSubscriber; use Drupal\Core\Routing\RouteMatchInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\KernelEvents; /** * 校验JSON:API请求的domain参数是否存在 */ class DomainParameterCheckSubscriber implements EventSubscriberInterface { /** * 当前路由匹配服务 * * @var \Drupal\Core\Routing\RouteMatchInterface */ protected $routeMatch; /** * 构造方法 * * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * 当前路由匹配服务实例 */ public function __construct(RouteMatchInterface $route_match) { $this->routeMatch = $route_match; } /** * {@inheritdoc} */ public static function getSubscribedEvents() { // 优先级设置为300,早于JSON:API的请求处理逻辑执行 $events[KernelEvents::REQUEST][] = ['checkDomainParameter', 300]; return $events; } /** * 校验请求是否携带domain参数 * * @param \Symfony\Component\HttpKernel\Event\RequestEvent $event * 请求事件实例 */ public function checkDomainParameter(RequestEvent $event) { $request = $event->getRequest(); // 仅处理JSON:API请求,不影响普通站点请求 if (strpos($request->getPathInfo(), '/jsonapi/') === FALSE) { return; } // 校验路径前缀的domain-parameter(匹配你示例的URL结构) $path_segments = explode('/', trim($request->getPathInfo(), '/')); $domain_parameter = $path_segments[0] ?? ''; // 如果是校验query参数中的domain-entity,替换为下面一行代码即可 // $domain_parameter = $request->query->get('domain-entity', ''); if (empty($domain_parameter)) { throw new BadRequestHttpException('Please, specify domain-parameter to get correct data'); } } }
4. 生效配置
启用自定义模块,执行drush cr清除Drupal缓存即可。
方案优势
- 完全遵循Drupal官方扩展规范,无需修改JSON:API、Domain Access等第三方模块的核心代码,后续版本升级无兼容风险
- 校验逻辑执行时机早,在业务逻辑处理前就拦截无效请求,不会浪费系统资源
- 抛出的异常会自动被JSON:API模块按标准格式返回,无需额外处理响应结构
- 后续调整校验规则只需修改订阅器代码,扩展性强
内容的提问来源于stack exchange,提问作者Yaroslav
相关产品推荐
相关产品推荐

