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

Drupal多值自定义字段必填验证:非全空时需通过验证

解决Drupal自定义多值字段的必填验证问题

我来帮你搞定这个Drupal自定义字段的验证难题~你遇到的核心问题是:给子字段设置了#required后,Drupal会先单独验证每个子元素的必填性,这就导致即使你通过hook_field_is_empty判断整个项是否为空,表单还是会因为最后一个空的子字段而触发必填错误。

解决方案步骤

我们需要调整验证逻辑,不再依赖子字段的#required,而是通过自定义验证来控制整个多值字段的必填规则:

  1. 移除子元素的#required属性
    首先在hook_field_widget_form里,不要给address或other子字段设置#required,因为我们要自己控制验证逻辑。

  2. 添加自定义字段验证回调
    在字段元素上添加自定义验证函数,检查整个多值字段是否至少有一个填写了有效内容的项。

  3. 确保hook_field_is_empty逻辑正确
    这个钩子主要影响字段的存储和显示,要保证它能正确判断单个项是否为空。

完整代码示例

1. 修改MYMODULE_field_widget_form

function MYMODULE_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  // 构建address子字段,不要设置#required
  $element['address'] = [
    '#type' => 'textfield',
    '#title' => t('Address'),
    '#default_value' => isset($items[$delta]['address']) ? $items[$delta]['address'] : '',
  ];

  // 构建other子字段,同样不设置#required
  $element['other'] = [
    '#type' => 'textfield',
    '#title' => t('Other'),
    '#default_value' => isset($items[$delta]['other']) ? $items[$delta]['other'] : '',
  ];

  // 如果字段是必填的,添加自定义验证回调
  if ($instance['required']) {
    $element['#element_validate'][] = 'MYMODULE_multivalue_field_validate';
  }

  return $element;
}

2. 实现自定义验证函数

function MYMODULE_multivalue_field_validate($element, &$form_state, $form) {
  // 获取当前字段的名称和语言代码
  $field_name = $element['#field_name'];
  $langcode = $element['#language'];
  // 获取所有多值项
  $items = $form_state['values'][$field_name][$langcode];

  // 检查是否存在至少一个填写了内容的项
  $has_valid_item = false;
  foreach ($items as $item) {
    // 只要address或other有一个不为空,就算有效项
    if (!empty($item['address']) || !empty($item['other'])) {
      $has_valid_item = true;
      break;
    }
  }

  // 如果没有任何有效项,触发表单错误
  if (!$has_valid_item) {
    form_error($element, t('至少需要填写一个字段内容。'));
  }
}

3. 修正hook_field_is_empty

function MYMODULE_field_is_empty($item, $field) {
  // 当address和other都为空时,这个项才被判定为空
  return empty($item['address']) && empty($item['other']);
}

为什么这样能解决问题?

  • 移除子字段的#required后,Drupal不会再单独验证每个子元素是否必填;
  • 自定义验证函数会检查整个多值字段的所有项,只要有一个项填写了内容,就通过验证,完美符合你“至少一个字段填写、最后一个空也能过”的需求;
  • hook_field_is_empty保证了空的项不会被存储到数据库里,避免冗余数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:19:25