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

Drupal 9通过自定义模块Hook计算时间差至Computed Field

解决方案:通过hook_entity_presave实现时间差计算并赋值给计算字段

针对你的Drupal 9.4.3 + PHP 8.1.6场景,以下是可行的自定义模块Hook实现方案,解决计算字段赋值无效的问题:

核心思路

使用hook_entity_presave()在节点保存前触发计算逻辑,确保时间差数值被正确写入computed_decimal字段。该Hook的执行时机能覆盖节点新建、编辑的场景,且能保证计算值被持久化到数据库。

代码实现

假设你的自定义模块机器名为hours_calculator,目标内容类型机器名为your_content_type(请替换为实际值),代码如下:

/**
 * Implements hook_entity_presave().
 */
function hours_calculator_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {
  // 仅处理目标内容类型的节点实体
  if ($entity->getEntityTypeId() !== 'node' || $entity->bundle() !== 'your_content_type') {
    return;
  }

  // 获取时间范围字段的原始值
  $time_range_data = $entity->get('field_friday_hours')->getValue();
  $total_hours = 0;

  // 检查时间范围的开始/结束值是否存在
  if (!empty($time_range_data[0]['value']) && !empty($time_range_data[0]['end_value'])) {
    // 将时间字符串转换为DateTime对象(兼容time_range模块的纯时间格式)
    $start = new DateTime($time_range_data[0]['value']);
    $end = new DateTime($time_range_data[0]['end_value']);

    // 计算时间差并转换为小时数(保留2位小数,可根据字段配置调整)
    $interval = $end->diff($start);
    $total_hours = $interval->h + ($interval->i / 60) + ($interval->s / 3600);
    $total_hours = round($total_hours, 2);
  }

  // 赋值给计算字段
  $entity->set('field_test_total_hours', $total_hours);
}

关键注意事项

  • Hook时机选择:避免使用hook_form_alter或其他非实体保存阶段的Hook,这些Hook无法确保计算值被写入数据库;hook_entity_presave是实体保存前的最后触发点,能保证值被持久化。
  • 字段值获取:datetime_range字段的单值数据存储在数组的[0]['value'](开始时间)和[0]['end_value'](结束时间)中,需确保非空再进行计算。
  • 时间差计算:使用DateTime::diff()获取时间间隔,再将小时、分钟、秒转换为总小时数,适配纯时间输入的场景(日期部分不影响差值计算)。
  • 模块启用与缓存:写完代码后启用自定义模块,执行drush cr或在后台清除缓存,确保Hook被Drupal识别。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 03:18:16