【问题标题】:Drupal 8 or 9 Save data to the content type from a custom moduleDrupal 8 或 9 将数据从自定义模块保存到内容类型
【发布时间】:2020-11-23 14:26:27
【问题描述】:

我正在使用 drupal 8.9.*,我想将数据从自定义模块保存到内容类型,以便我可以看到在 Drupal 的通用内容列表页面中输入的数据。

我不知道如何将数据保存到内容类型,我尝试过使用 $node 的对象来保存它(以及我尝试过的其他一些方法,但后来知道它已被弃用)。我还传递了内容类型的机器名称。我在哪里出错了,所有的 Drupal 文档都被扭曲了,很难找到正确的 8 版本 || 9. 这是我的代码。

路由数据文件,birth_details.routing.yml

birth_details.newreading:
  path: '/new-reading'
  defaults: 
    _title: 'Enter the birth details for reading'
    _form: '\Drupal\birth_details\Form\BirthDetails'
  requirements: 
    _permission: 'access content'

我的表格 BirthDetails.php,(硬编码一些值用于测试目的)

<?php
    namespace Drupal\birth_details\Form;

    use Drupal\Core\Form\FormBase;
    use Drupal\Core\Form\FormStateInterface;

    class BirthDetails extends FormBase {

        public function getFormId(){
            return 'birth_data';
        }

        public function buildForm(array $form, FormStateInterface $form_state){

            $form['title'] =  [
                '#type' => 'textfield',
                '#description' => $this->t('Enter your name here!'),
            ];
            $form['field_birth_date'] =  [
                '#type' => 'textfield',
                '#description' => $this->t('Enter your field_birth_date here!'),
            ];
            $form['field_birth_location'] =  [
                '#type' => 'textfield',
                '#description' => $this->t('Enter your field_birth_location here!'),
            ];
            $form['field_email_id'] =  [
                '#type' => 'textfield',
                '#description' => $this->t('Enter your field_email_id here!'),
            ];
            $form['field_gender'] =  [
                '#type' => 'textfield',
                '#description' => $this->t('Enter your field_gender here!'),
            ];

            $form['actions']['#type'] = 'actions';
            $form['actions']['submit'] = [
                '#type' => 'submit',
                '#value' => $this->t('Save data'),
                
            ];

            return $form;
        }

        public function submitForm(array &$form, FormStateInterface $form_state){
            $node = new stdClass();
            $node = Node::create([
              'type' => 'birth_data',
              'title' => 'first lastname',
              'field_birth_date' => '23 NOV 2020 11:11:11',
              'field_birth_location' => 'Osaka',
              'field_email_id' => 'test@myid.com',
              'field_gender' => 'Male',
            ]);
            $node->save();  
            echo "<pre>";
            print_r($form_state);
            exit;

        }
    }

最后自定义内容类型的机器名称是birth_data,我对form unique id和节点创建类型type使用相同

【问题讨论】:

标签: php drupal-8 drupal-modules drupal-9


【解决方案1】:

Baikho 的回答很好。还是尽量避免使用静态调用(比如Node::create());我们可以很容易地在构造函数中注入依赖项。

<?php

namespace Drupal\birth_details\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

class BirthDetails extends FormBase {

  /**
   * Current user account.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * Node storage.
   *
   * @var \Drupal\node\NodeStorageInterface
   */
  protected $nodeManager;

  /**
   * {@inheritdoc}
   */
  public function __construct(
    EntityTypeManager $entity_type_manager,
    AccountProxyInterface $current_user
  ) {
    $this->currentUser = $current_user;
    $this->nodeManager = $entity_type_manager->getStorage('node');
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager'),
      $container->get('current_user')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId(){
    return 'birth_data';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['title'] =  [
      '#type' => 'textfield',
      '#description' => $this->t('Enter your name here!'),
    ];
    $form['field_birth_date'] =  [
      '#type' => 'textfield',
      '#description' => $this->t('Enter your field_birth_date here!'),
    ];
    $form['field_birth_location'] =  [
      '#type' => 'textfield',
      '#description' => $this->t('Enter your field_birth_location here!'),
    ];
    $form['field_email_id'] =  [
      '#type' => 'textfield',
      '#description' => $this->t('Enter your field_email_id here!'),
    ];
    $form['field_gender'] =  [
      '#type' => 'textfield',
      '#description' => $this->t('Enter your field_gender here!'),
    ];

    $form['actions']['#type'] = 'actions';
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Save data'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {

  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $node = $this->nodeManager->create([
      'type' => 'birth_data',
      'title' => $values['title'],
      'uid' => $this->currentUser->id(),
      'status' => 1,
    ]);

    $node->field_birth_date->value = "23 NOV 2020 11:11:11";
    $node->field_birth_location->value = "Osaka";
    $node->field_email_id->value = "test@myid.com";
    $node->field_gender->value = "Male";
    
    $node->save();
  }
}

【讨论】:

  • 刚刚添加使用 Psr\Container\ContainerInterface;为我工作
  • 哎呀我的错...实际上应该是use Symfony\Component\DependencyInjection\ContainerInterface;;我编辑了答案;)
【解决方案2】:

这一行是多余的,你可以丢弃它:

$node = new stdClass();

假设您有一个内容类型,即创建节点的一个可能示例。 page:

use Drupal\node\Entity\Node;

...

// Initialise a node object with several field values.
$node = Node::create([
  'type' => 'page',
  'title' => 'foo',
  'field_birth_date' => ['value' => 'bar'],
]);

// Set field values.
$node->field_birth_date->value = 'bar';
$node->field_birth_location->value = 'US';
$node->field_email_id->value = 'hello@example.com';
$node->field_gender->value = 'm'

// You can also use setters but you need to check on the available ones. They are also chainable:
$node
  ->setTitle('foo')
  ->setPromoted(TRUE)
  ->setPublished();

// Save the node.
$node->save();

【讨论】:

    【解决方案3】:

    您的解决方案与BaikhoMacSim 的建议应该可以工作,但这并没有完全利用 Drupal 的自定义内容类型设计。您正在创建一个表单,并使用该表单将信息路由到一个节点,该节点提供了在不维护自己的表单的情况下执行您想要的操作的机制。

    如果您想create a custom node type,您可以让您的模块在安装期间定义节点包类型,然后使用标准界面输入和编辑该内容。如果你想从那里修改表单,你应该使用hook_BASEID_form_alter()

    您的另一个选择是创建一个custom content entity,这实际上是创建另一个与节点平行的元素。

    【讨论】:

    • 谢谢...我刚开始学习 Drupal,在概念上和实践上有点难以理解...但是 1-2 周后我将能够理解您的帖子
    • 我曾经在 Drupal 4 和 5 上工作过……但今天 Drupal 处于完全不同的水平
    • 因此,如果您还记得 CCK 从 5(或 4.x 中的 flexinode)开始,那在 D6 中就进入了核心,并真正改变了平台的工作方式。过去需要自定义模块的东西变成了基于点击的配置。有了 D8,这一切都变得易于部署。有时仍然有足够的空间用于良好的自定义模块,它们只是现在不同类型的东西所需要的。
    • 有时我们需要从前端保存。
    猜你喜欢
    • 1970-01-01
    • 2017-04-19
    • 1970-01-01
    • 2016-12-15
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 2016-06-25
    • 2018-06-21
    相关资源
    最近更新 更多