【问题标题】:How to manipulate value before node is saved in Drupal 8?如何在节点保存在 Drupal 8 之前操作值?
【发布时间】:2018-11-02 02:34:31
【问题描述】:

我有一个编辑节点表单。当用户输入新值并单击提交以编辑节点时,我首先想取回旧节点,操作该值,然后保存/更新节点。

以下是我的解决方案,但它不起作用。

function custom_module_form_node_form_alter(&$form, FormStateInterface $form_state) {
    $editing_entity = $form_state->getFormObject()->getEntity();

    if (!$editing_entity->isNew()) {
        $form['actions']['submit']['#submit'][] = 'custom_module_node_form_submit';
    }
}

function custom_module_node_form_submit($form, FormStateInterface $form_state) {
   $editing_entity = $form_state->getFormObject()->getEntity();

   $entity = Drupal::entityTypeManager()->getStorage('node')->load($editing_entity->id());
}

在 form_submit 钩子中,我试图取回旧节点,但已经太晚了,节点已经更新/保存。在 Drupal 8 中更新/保存节点之前,如何取回旧节点并操作值?

【问题讨论】:

    标签: php drupal drupal-8


    【解决方案1】:

    尝试使用hook_entity_presave()

    /**
     * Implements hook_entity_presave().
     */
    function YOUR_MODULE_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {
      switch ($entity->bundle()) {
        // Here you modify only your day content type
        case 'day':
          // Setting the title with the value of field_date.
          $entity->setTitle($entity->get('field_date')->value);
         break;
      }
    }
    

    从这里获取的解决方案:https://drupal.stackexchange.com/questions/194456/how-to-use-presave-hook-to-save-a-field-value-as-node-title

    您还可以获得旧值,例如:$entity->original。在这里查看:

    https://drupal.stackexchange.com/questions/219559/how-to-get-the-original-entity-on-hook-entity-presave

    【讨论】:

    • 感谢您的解决方案。我看过这个钩子。但是太笼统了。我正在寻找更具体的东西,因为 presave 钩子适用于所有保存操作。我现在正在尝试 form_validate 钩子,我可以在保存之前操纵该值。告诉我你对 form_validate 钩子的看法。
    • 更新了我关于如何获取旧值的答案。不明白你所说的“太笼统”是什么意思?!?为什么你不能使用它?您是否需要在某些情况下取消验证表单(防止成功保存)?
    • 太笼统了,我的意思是当你保存节点、术语、用户等所有内容时会调用 presave 钩子。这就是我们在 presave 钩子中使用 switch 语句的原因。但是您的解决方案效果很好。
    • 是的,正如 Kris 解释的那样,您可以拥有挂钩所有实体类型或将实体类型添加到函数名称的通用。但是点是一样的。
    • 如果您只对节点实体感兴趣,使用 hook_ENTITY_TYPE_presave 会更好:stackoverflow.com/a/50487513/382177
    【解决方案2】:

    我决定如下操作表单验证钩子中的值。

    function custom_module_form_node_form_alter(&$form, FormStateInterface $form_state) {
        $editing_entity = $form_state->getFormObject()->getEntity();
    
        if (!$editing_entity->isNew()) {
            $form['#validate'][] = 'custom_module_node_form_validate';
        }
    }
    
    function custom_module_node_form_validate(array &$form, FormStateInterface $form_state) {
        $old_entity = $form_state->getFormObject()->getEntity();
        $old_values = $old_entity->get('field_name')->getValue()
    
        $new_values = $form_state->getValue('field_name');
    
        // Manipulate and store desired values to be save here.
        $to_save_value = ['a', 'b', 'c'];
        $form_state->setValue('field_name', $to_save_value);
    }
    

    【讨论】:

    • 我选择了这个解决方案,因为这个钩子不仅可以像 hook_node_presave 一样在自定义模块的上下文中工作,而且它也可以在自定义主题文件的上下文中实现
    【解决方案3】:

    使用hook_ENTITY_TYPE_presave,像这样:

    function yourmodulename_node_presave(Drupal\node\NodeInterface $entity) {
        if ($entity->getType() == 'your_content_type') {
           $entity->setTitle('Hello');
           $entity->set('body', 'this is body');
        } 
    }
    

    这是最好的解决方案,因为像 MilanG 这样的 hook_form_alter 只有在节点从您正在更改的特定表单中保存时,您才会更改值!如果节点是从代码中以编程方式或通过其他方法保存的,您的 hook_form_alter 将不会启动。

    【讨论】:

    • 这不是很有帮助。你所做的只是复制钩子签名。它无法显示如何实际设置字段值...尤其是没有魔术方法的字段之一(例如 setTitle())。
    • @sea26.2 我根据您的评论改进了代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 1970-01-01
    • 2016-09-04
    相关资源
    最近更新 更多