You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 06:54:04