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

Drupal 8:如何在节点保存前获取旧节点并修改值?

解决Drupal 8节点编辑时在保存前获取旧数据并修改的问题

你遇到的问题我太熟悉了——Drupal节点表单的默认提交回调会先完成节点保存操作,而你把自定义回调追加到#submit数组末尾,时机确实太晚了,自然拿不到原始的旧数据。下面给你两个靠谱的解决办法,都能在节点保存前拿到旧数据并修改:

方案一:使用hook_entity_presave(推荐,通用型)

这个钩子会在任何实体(包括节点)保存之前触发,不管是通过表单提交还是API操作,适用性更广。你可以在这里加载数据库里的原始节点数据,对比后修改当前实体的值,系统会自动处理后续的保存流程。

/**
 * Implements hook_entity_presave().
 */
function custom_module_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {
  // 仅处理节点类型,且是更新操作(排除新建节点)
  if ($entity->getEntityTypeId() === 'node' && !$entity->isNew()) {
    // 加载数据库里的原始旧节点数据(未被当前表单修改的版本)
    $old_node = Drupal::entityTypeManager()->getStorage('node')->loadUnchanged($entity->id());
    
    // 示例:对比旧标题,修改新标题
    if ($old_node->getTitle() === '旧标题') {
      $entity->setTitle('修改后的新标题');
    }
    
    // 示例:把旧内容追加到新内容后面
    $old_body = $old_node->get('body')->value;
    $new_body = $entity->get('body')->value;
    $entity->set('body', $new_body . '<br><strong>原内容:</strong>' . $old_body);
    
    // 无需手动调用$entity->save(),钩子执行后系统会自动完成保存
  }
}

方案二:调整表单提交回调的执行顺序(表单专属)

如果你只需要在用户通过编辑表单提交时处理,可以调整#submit数组的顺序,让你的自定义回调在默认的节点保存回调之前执行:

function custom_module_form_node_form_alter(&$form, FormStateInterface $form_state) {
  $editing_entity = $form_state->getFormObject()->getEntity();
  if (!$editing_entity->isNew()) {
    // 找到默认的节点表单提交回调的位置
    $default_submit_key = array_search('node_form_submit', $form['actions']['submit']['#submit']);
    if ($default_submit_key !== FALSE) {
      // 先移除默认回调,再重新添加顺序:自定义回调在前,默认回调在后
      unset($form['actions']['submit']['#submit'][$default_submit_key]);
      $form['actions']['submit']['#submit'][] = 'custom_module_node_form_submit';
      $form['actions']['submit']['#submit'][] = 'node_form_submit';
    }
  }
}

function custom_module_node_form_submit($form, FormStateInterface $form_state) {
  $editing_entity = $form_state->getFormObject()->getEntity();
  // 加载原始旧节点数据
  $old_node = Drupal::entityTypeManager()->getStorage('node')->loadUnchanged($editing_entity->id());
  
  // 在这里根据旧数据修改当前实体的值,示例:
  $old_field_value = $old_node->get('field_custom')->value;
  $editing_entity->set('field_custom', $old_field_value . '-追加内容');
  
  // 不要手动调用save(),后面的node_form_submit会处理保存
}

关键注意点

  • 一定要用loadUnchanged()而不是普通的load(),前者会直接从数据库读取未修改的原始数据,后者可能拿到的是已经被表单修改过的缓存实体。
  • 不要在回调里手动调用$entity->save(),否则会导致节点被保存两次,可能引发不必要的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:42:56