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

Drupal 11:如何创建由外部API填充的多选作者字段?

实现步骤与方向指引

你不需要自定义整个内容类型,只需要开发自定义字段类型+字段小部件+字段格式化器,就能通过Drupal UI把这个作者字段添加到Blog内容类型中。以下是具体实现路径:

1. 搭建基础自定义模块

先创建一个标准的Drupal自定义模块(比如命名为external_author),包含必要的external_author.info.yml、external_author.module文件,这是所有自定义字段开发的基础。

2. 定义自定义字段类型(存储外部ID)

字段类型负责定义数据存储结构,我们只需要存储外部API返回的id值(支持多选):

  • 创建src/Plugin/Field/FieldType/ExternalAuthorItem.php文件,继承FieldItemBase
  • 用注解@FieldType声明字段类型,设置标签、描述、基数(设为-1支持多选)
  • 在schema()方法中定义存储结构,示例代码:
public static function schema(FieldStorageDefinitionInterface $field_definition) {
  return [
    'columns' => [
      'target_id' => [
        'type' => 'varchar',
        'length' => 255,
        'not null' => FALSE,
      ],
    ],
  ];
}
  • 实现isEmpty()、propertyDefinitions()等必要方法,确保字段能正常存储和验证。

3. 实现字段小部件(渲染多选下拉框)

字段小部件负责在内容编辑表单中渲染多选下拉,从外部API拉取选项并显示:

  • 创建src/Plugin/Field/FieldWidget/ExternalAuthorSelectWidget.php文件,继承WidgetBase
  • 用注解@FieldWidget声明小部件,关联到之前定义的字段类型
  • 在formElement()方法中构建多选下拉表单元素,关键逻辑示例:
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
  // 调用外部API获取作者列表,处理请求与错误
  $authors = $this->getExternalAuthors();
  
  // 转换为Drupal表单选项格式:[id => label]
  $options = [];
  foreach ($authors as $author) {
    $options[$author['id']] = $author['label'];
  }

  $element['target_id'] = $element + [
    '#type' => 'select',
    '#title' => $this->t('Author'),
    '#options' => $options,
    '#multiple' => TRUE, // 开启多选
    '#default_value' => array_column($items->getValue(), 'target_id'), // 加载已选值
  ];

  return $element;
}

// 封装API调用并添加缓存
private function getExternalAuthors() {
  $cache = \Drupal::cache();
  $cachedData = $cache->get('external_authors_list');
  
  if ($cachedData) {
    return $cachedData->data;
  }

  $client = \Drupal::httpClient();
  try {
    $response = $client->get('你的外部API地址', [
      'headers' => ['Accept' => 'application/json'],
    ]);
    $data = json_decode($response->getBody(), TRUE);
    // 缓存1小时,可根据需求调整
    $cache->set('external_authors_list', $data, time() + 3600);
    return $data;
  } catch (\Exception $e) {
    \Drupal::logger('external_author')->error('Failed to fetch authors: @message', ['@message' => $e->getMessage()]);
    return [];
  }
}

4. 实现字段格式化器(显示作者名称)

字段格式化器负责在内容前端显示存储的ID对应的作者名称:

  • 创建src/Plugin/Field/FieldFormatter/ExternalAuthorNameFormatter.php文件,继承FormatterBase
  • 用注解@FieldFormatter声明格式化器,关联字段类型
  • 在viewElements()方法中匹配ID与名称,示例代码:
public function viewElements(FieldItemListInterface $items, $langcode) {
  $elements = [];
  $authorIds = array_column($items->getValue(), 'target_id');
  if (empty($authorIds)) {
    return $elements;
  }

  $authors = $this->getExternalAuthors();
  $authorMap = array_column($authors, 'label', 'id');

  foreach ($authorIds as $id) {
    if (isset($authorMap[$id])) {
      $elements[] = [
        '#markup' => $authorMap[$id],
      ];
    }
  }

  return $elements;
}

// 复用API调用方法(或提取为公共服务)
private function getExternalAuthors() {
  // 同小部件中的API调用+缓存逻辑
}

5. 通过UI配置Blog内容类型

  • 进入Drupal后台结构 > 内容类型,创建Blog内容类型
  • 标题字段默认已存在,添加一个长文本字段作为描述
  • 添加字段时选择你自定义的「外部作者」字段类型,配置字段为多选,选择对应的「多选下拉」小部件,前端显示用「作者名称」格式化器

关键注意事项

  • 缓存策略:外部API数据如果更新不频繁,一定要加缓存;若需实时更新,可调整缓存时间或添加缓存标签让Drupal自动失效。
  • 异常处理:必须处理API请求失败的情况,避免页面崩溃。
  • 字段验证:可在字段类型的validate()方法中添加逻辑,确保存储的ID在外部API中存在。

内容的提问来源于stack exchange,提问作者importTurtle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 07:31:12