Drupal 10:hook_entity_insert 和 hook_entity_update 不适用于段落标记

问题描述 投票:0回答:1

我正在开发一个 Drupal 10 模块,该模块实现

hook_entity_insert
hook_entity_update
以在创建或更新节点时自动标记节点中的
event
类型段落。钩子触发逻辑检查段落,将标签与节点组进行比较,并添加任何缺失的标签。

当钩子被触发时,段落并没有得到更新。日志有时会显示如下消息:

  • “未找到段落”
  • “节点未与组关联”

…尽管数据明显存在。没有抛出任何错误——只是……什么也没发生。

  1. 我是否需要在这些挂钩内重新加载实体(如段落或组)以确保数据是最新的?
  2. 是否有任何
    hook_entity_insert
    hook_entity_update
    的怪癖可能导致此行为?
  3. 问题可能出在我用于检索引用实体或组数据的自定义辅助函数中吗?

任何建议或见解将不胜感激!下面是相关代码:

/**
 * Implements hook_entity_insert().
 */
function my_module_entity_insert(EntityInterface $entity) {
  if ($entity instanceof NodeInterface) {
    my_module_handle_event_paragraph_tagging($entity);
  }
}

/**
 * Implements hook_entity_update().
 */
function my_module_entity_update(EntityInterface $entity) {
  if ($entity instanceof NodeInterface) {
    my_module_handle_event_paragraph_tagging($entity);
  }
}

/**
 * Handles tagging for paragraphs of type 'event' in a given node.
 *
 * @param \Drupal\node\NodeInterface $entity
 *   The node entity being saved. This node contains referenced paragraphs.
 */
function my_module_handle_event_paragraph_tagging(NodeInterface $entity) {
  if (!$entity->hasField('field_content_function')) {
    \Drupal::logger('my_module')->warning('Node @id does not have field_content_function.', ['@id' => $entity->id()]);
    return;
  }

  $paragraphs = FieldHelper::getReferencedEntities($entity, 'field_content_function');
  if (empty($paragraphs)) {
    \Drupal::logger('my_module')->notice('No paragraphs found in field_content_function for node @id.', ['@id' => $entity->id()]);
    return;
  }

  $group = EntityHelper::getGroup($entity); 
  if (!$group) {
    \Drupal::logger('my_module')->warning('Node @id is not associated with a group.', ['@id' => $entity->id()]);
    return;
  }

  $auto_main_tag_groups = FieldHelper::getReferencedEntities($group, 'field_auto_main_tagged_groups') ?? [];
  $auto_main_tag_group_ids = array_map(fn($g) => $g->id(), $auto_main_tag_groups);

  foreach ($paragraphs as $paragraph) {
    if ($paragraph->bundle() !== 'event') {
      continue;
    }

    $main_event_list_groups = FieldHelper::getReferencedEntities($paragraph, 'field_main_tagged_groups') ?? [];
    $main_event_list_group_ids = array_map(fn($g) => $g->id(), $main_event_list_groups);

    $groups_to_add = array_diff($auto_main_tag_group_ids, $main_event_list_group_ids);

    foreach ($groups_to_add as $group_id) {
      $paragraph->get('field_main_tagged_groups')->appendItem(['target_id' => $group_id]);
    }

    try {
      $paragraph->save();
    } catch (\Exception $e) {
      \Drupal::logger('my_module')->error('Error saving paragraph @id: @message', [
        '@id' => $paragraph->id(),
        '@message' => $e->getMessage(),
      ]);
    }
  }
}

/**
 * Retrieves the group associated with a node.
 *
 * @param \Drupal\node\NodeInterface $node
 *   The node entity.
 *
 * @return \Drupal\group\Entity\Group|null
 *   The associated group entity, or NULL if no group is found.
 */
function my_module_get_group(NodeInterface $node) {
  $group = FieldHelper::getReferencedEntities($node, 'field_group');
  if (!empty($group)) {
    return reset($group);
  }

  if ($node->hasField('field_parent_node')) {
    $parent = FieldHelper::getReferencedEntities($node, 'field_parent_node');
    if (!empty($parent) && $parent[0] instanceof NodeInterface) {
      return my_module_get_group($parent[0]); 
    }
  }

  \Drupal::logger('my_module')->warning('No group found for node @id.', ['@id' => $node->id()]);
  return NULL;
}

如果您遇到类似的情况或对我可能缺少的内容有想法,请告诉我。提前致谢! 🙏

php drupal drupal-10
1个回答
0
投票

hook_entity_update

文档
指出“一旦更新实体存储,此挂钩就会运行。请注意,挂钩实现可能不会更改存储的实体数据。 ...”。

此挂钩内的更改将不会被保存,因为在更新已保存到数据库后会触发该事件。

您需要查看

hook_entity_presave
,它在实体保存到数据库之前但在应用所有字段更新之后在实体创建和更新时触发。 https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21entity.api.php/function/hook_ENTITY_TYPE_presave/10

插入和更新钩子都可以用这个钩子替换:

/**
 * Implements hook_entity_presave().
 */
function my_module_entity_presave(EntityInterface $entity): void {
  if ($entity instanceof NodeInterface) {
    my_module_handle_event_paragraph_tagging($entity);
  }
}

如果您订阅的实体始终是一个节点,您可以在钩子中指定它,使代码更小且更具可读性。

/**
 * Implements hook_entity_presave().
 */
function my_module_node_presave(NodeInterface $node): void {
  my_module_handle_event_paragraph_tagging($node);
}
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.