Create a node programmatically in Drupal 8

Many of the changes from Drupal 7 to Drupal 8 involve the use of object oriented code. One particular change is to move away from code specific to nodes to writing the code for entities and then overriding or extending it where necessary for nodes. Conceptually, this results in being able to use much of the same code for other entities including custom entities.

One of the problems with searching for information on the web is that the instructions may apply to different versions of software than someone is trying to use and often the versions of software are not mentioned in the instructions.  Even more insidious is when the information for a particular version of software changes before it is released.  An example is creating a node programmatically in Drupal 8.  Some instructions will use the function entity_create().  While this function was introduced for Drupal 8 it has already been deprecated.  The documentation suggests using "The method overriding Entity::create(), e.g. \Drupal\node\Entity\Node::create() if the entity type is known."  But searching for examples shows fewer results than for entity_create().  Searching the code in Drupal 8 brings up extensive use of entity_create().  So now that Drupal 8 has actually been released (November 19, 2015) this article looks at three different ways of creating a node programmatically for Drupal 8.

A module called mymodule is used to try the different approaches. Starting with mymodule.info.yml:

name: My Module
type: module
description: My module functionality.
package: Other
core: 8.x

The route is specified in mymodule.routing.yml

mymodule.example:
  path: 'mymodule/example'
  defaults:
    _form: '\Drupal\mymodule\Form\MyModuleExample'
    _title: 'My Module Example'
  requirements:
    _permission:  'access content'

The bulk of the code goes into our form in src/Form/MyModuleExample.php

<?php

/**
 * @file
 * Contains \Drupal\mymodule\Form\MyModuleExample.
 */

namespace Drupal\mymodule\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\node\Entity\Node;

/**
 * My Module example.
 */
class MyModuleExample extends FormBase {

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

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form = array();

    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Create node'),
    );

    return $form;
  }

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

    // Code for creating a node goes here.

    drupal_set_message(t('Created new node'));
  }

}

?>

The code for creating a node using entity_create is

$values = array(
  'nid' => NULL,
  'type' => 'article',
  'title' => 'Create node using entity_create()',
  'uid' => 1,
  'status' => TRUE,
);
entity_create('node', $values)->save();

Replace the comment in the submitForm() function and then go to the website URL with the path mymodule/example. The press the "Create node" button to test the code. Then look at the content page to find the new node. If the node is needed then do not chain the save() function.

$values = array(
  'nid' => NULL,
  'type' => 'article',
  'title' => 'Create node using entity_create()',
  'uid' => 1,
  'status' => TRUE,
);
$node = entity_create('node', $values);
$node->save();
// Do something with $node.

The problem with this approach is that it is not object oriented. So it has been deprecated in favor of the following.

$node = Node::create(array(
  'nid' => NULL,
  'type' => 'article',
  'title' => 'Create node using Node::create()',
  'uid' => 1,
  'status' => TRUE,
));
$node->save();
// Do something with $node.

The save function can be chained if the $node object is not needed. The following line was already included at the beginning of the file.

use Drupal\node\Entity\Node;

This approach only works for nodes while entity_create() works for any entity. The documentation also suggests "If the entity type is variable, use the entity storage's create method to construct a new entity." In Entity.php the create() function is

public static function create(array $values = array()) {
  $entity_manager = \Drupal::entityManager();
  return $entity_manager->getStorage($entity_manager->getEntityTypeFromClass(get_called_class()))->create($values);
}

Untangling this code results in the following code for our submitForm() function.

$values = array(
  'nid' => NULL,
  'type' => 'article',
  'title' => 'Create node using Node storage create method',
  'uid' => 1,
  'status' => TRUE,
);
$node = \Drupal::entityManager()->getStorage('node')->create($values);
$node->save();

This code can handle variable entity types although the values passed in the $values array would be different. But just before Drupal 8 was released, the EntityManager object was deprecated. The EntityManager will be split up into smaller objects so this code will change.

p.s. 1/5/2016: While I thought when I first tried to create a node in Drupal 8 that it would be relatively simple I was surprised at the lack of information and amount of work it took to figure out how to do a fairly simple task.  Today the issue Decide how to create/load entities in procedural code and test classes was created.

Categories