1

I am using drupal 8.9.*, I want to Save data to the content type from a custom module so that i can see the data entered in Drupal's common content list page.

I dont know how to save data to the content type, I have tried using object of $node to save it (and some other method I tried but later came to know its deprecated). I have also passed machine-name of the content type. Where I am going wrong on this, all the Drupal documentation is distorted, hard to find a correct version of 8 || 9. Here is my code.

Routing data file, 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'

My form BirthDetails.php, (hard coded some values for testing purpose)

<?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;

        }
    }

and finally machine name of the custom content type is birth_data, i have used the same for form unique id and node create type type

Mangesh Sathe
  • 1,987
  • 4
  • 21
  • 40
  • I have moved updated code to GIT, for beginners like me, its for learning purpose only https://github.com/SatheMangesh/birth_details – Mangesh Sathe Nov 28 '20 at 11:27

3 Answers3

4

Baikho's answer is nice. It's still better to avoid the use of static calls (such as Node::create()) ; we can easily do this injecting dependencies in the constructor.

<?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();
  }
}
MacSim
  • 374
  • 3
  • 10
3

This line is redundant, you can discard it:

$node = new stdClass();

A possible example of creating a node, assuming you have a Content Type ie. 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();
baikho
  • 5,203
  • 4
  • 40
  • 47
1

Your solution with the suggestions from Baikho or MacSim should work, but that doesn't fully leverage Drupal's design for custom content types. You are creating a form, and using that to route information into a node which provides mechanisms to do what you want without maintaining your own form.

If you want to create a custom node type, you can have your module define the node bundle type during install and then use the standard interface to enter and edit that content. If you want to modify the form from there you should use the hook_BASEID_form_alter()

Your other option is to create a custom content entity, which is essentially creating another element parallel to the nodes.

acrosman
  • 12,814
  • 10
  • 39
  • 55
  • Thanks...finding bit difficult to understand conceptually and practically as I have just started learning Drupal....But in a 1-2 weeks time i will be in a position to understand your post – Mangesh Sathe Nov 28 '20 at 10:57
  • 1
    I used to work on Drupal 4 and 5...but today Drupal is at totally different level – Mangesh Sathe Nov 28 '20 at 11:00
  • So if you remember CCK from 5 (or flexinode in 4.x), that went into core back in D6, and really changed how the platform works. Things that used to require custom modules became click-based config. And with D8 it all became easily deployable. Still plenty of room for good custom modules at times, they are just needed for different types of things now. – acrosman Dec 01 '20 at 15:44
  • Sometimes we need to do save from front side. – khaled_webdev Sep 22 '21 at 08:43
  • I'm not sure this answers the question asked. It didn't refer to creating a custom content type. It was asking how to build a form that will save data to a content type (node). – welly Jun 15 '23 at 13:04