How to programmatically create a node in Drupal 8?

28,323

Solution 1

Figured it out. For anyone else with this issue, nodes are now treated as entities, and the entity module is now part of core. So my code ended up looking like this:

$new_page_values = array();
$new_page_values['type'] = 'my_content_type';
$new_page_values['title'] = $form_state['values']['page_title'];
$new_page_values['path'] = $new_page_path;

$new_page = entity_create('node', $new_page_values);
$new_page->save();

Solution 2

use Drupal\node\Entity\Node;

$node = Node::create(array(
    'type' => 'your_content_type',
    'title' => 'your title',
    'langcode' => 'en',
    'uid' => '1',
    'status' => 1,
    'field_fields' => array(),
));

$node->save();

Solution 3

RE: deprecated entity create

Here is a short example of usage without the deprecated functions. This is particularly helpful for dynamic creation:

//define entity type and bundle
$entity_type="node";
$bundle="article";

//get definition of target entity type
$entity_def = \Drupal::entityManager()->getDefinition($entity_type);

//load up an array for creation
$new_node=array(
  //set title
  'title' => 'test node',

  //set body
  'body' => 'this is a test body, can also be set as an array with "value" and "format" as keys I believe',

  //use the entity definition to set the appropriate property for the bundle
  $entity_def->get('entity_keys')['bundle']=>$bundle
);

$new_post = \Drupal::entityManager()->getStorage($entity_type)->create($new_node);
$new_post->save();

Solution 4

The D8 version of devel/devel_generate module has a good example of this.

From devel_generate :

  $edit_node = array(
    'nid' => NULL, 
    'type' => $node_type, 
    'uid' => $users[array_rand($users)], 
    'revision' => mt_rand(0, 1), 
    'status' => TRUE, 
    'promote' => mt_rand(0, 1), 
    'created' => REQUEST_TIME - mt_rand(0, $results['time_range']), 
    'langcode' => devel_generate_get_langcode($results),
  );
  if ($type->has_title) {
    // We should not use the random function if the value is not random
    if ($results['title_length'] < 2) {
      $edit_node['title'] = devel_create_greeking(1, TRUE);
    }
    else {
      $edit_node['title'] = devel_create_greeking(mt_rand(1, $results['title_length']), TRUE);
    }
  }
  else {
    $edit_node['title'] = '';
  }
  // @todo Remove once comment become field. http://drupal.org/node/731724
  if (Drupal::moduleHandler()->moduleExists('comment')) {
    $edit_node['comment'] = variable_get('comment_' . $node_type, COMMENT_NODE_OPEN);
  }
  $node = entity_create('node', $edit_node);

Using formatted text

Using grep with before/after code lines helped me figure out how to add a node with 'full_html'.

Search the Drupal core code with this :

$ cd drupal/core
$ grep -B 5 -A 5 -r entity_create.*node * > /tmp/temp-grep.txt

Then, open up /tmp/temp-grep.txt in a text editor. Poke around there a bit and you'll see this :

--
modules/editor/src/Tests/EditorFileUsageTest.php-    $body_value .= '<img src="awesome-llama.jpg" data-editor-file-uuid="invalid-editor-file-uuid-value" />';
modules/editor/src/Tests/EditorFileUsageTest.php-    // Test handling of a non-existing UUID.
modules/editor/src/Tests/EditorFileUsageTest.php-    $body_value .= '<img src="awesome-llama.jpg" data-editor-file-uuid="30aac704-ba2c-40fc-b609-9ed121aa90f4" />';
modules/editor/src/Tests/EditorFileUsageTest.php-    // Test editor_entity_insert(): increment.
modules/editor/src/Tests/EditorFileUsageTest.php-    $this->createUser();
modules/editor/src/Tests/EditorFileUsageTest.php:    $node = entity_create('node', array(
modules/editor/src/Tests/EditorFileUsageTest.php-      'type' => 'page',
modules/editor/src/Tests/EditorFileUsageTest.php-      'title' => 'test',
modules/editor/src/Tests/EditorFileUsageTest.php-      'body' => array(
modules/editor/src/Tests/EditorFileUsageTest.php-        'value' => $body_value,
modules/editor/src/Tests/EditorFileUsageTest.php-        'format' => 'filtered_html',
--

Note how 'body' now becomes an array with a 'value' and a 'format'.

Solution 5

Best way to create node in Drupal 8 via using core services

$node = \Drupal::entityTypeManager()->getStorage('node')->create([
  'type'       => 'content_type_machine_name',
  'field_text' => 'Foo',
  'title'      => 'Text Title',
]);
$node->save();
Share:
28,323
chapka
Author by

chapka

Updated on October 18, 2020

Comments

  • chapka
    chapka over 3 years

    I'm designing a new module in Drupal 8. It's a long-term project that won't be going public for a few months at least, so I'm using it as a way to figure out what's new.

    In this module, I want to be able to programmatically create nodes. In Drupal 7, I would do this by creating the object, then calling "node_submit" and "node_save".

    These functions no longer exist in Drupal 8. Instead, according to the documentation, "Modules and scripts may programmatically submit nodes using the usual form API pattern." I'm at a loss. What does this mean? I've used Form API to create forms in Drupal 7, but I don't get what the docs are saying here.

    What I'm looking to do is programmatically create at least one and possibly multiple new nodes, based on information not taken directly from a user-presented form. I need to be able to:

    1) Specify the content type

    2) Specify the URL path

    3) Set any other necessary variables that would previously have been handled by the now-obsolete node_object_prepare()

    4) Commit the new node object

    I would prefer to be able to do this in an independent, highly abstracted function not tied to a specific block or form.

    So what am I missing?

  • Oscar Nevarez
    Oscar Nevarez over 8 years
    I was about to suggest you to create the entity using the storage service but just noticed that thats what Drupal does internally in entity_create.
  • masterchief
    masterchief over 8 years
    entity_create is deprecated as per the documentation: @deprecated in Drupal 8.0.x, will be removed before Drupal 9.0.0. Use The method overriding Entity::create() for the entity type, e.g. \Drupal\node\Entity\Node::create() if the entity type is known. If the entity type is variable, use the entity storage's create() method to construct a new entity: See drupal.stackexchange.com/a/108874/1895
  • J-P
    J-P over 7 years
    A couple more things have been deprecated or changed since this was written: \Drupal::entityManager() should become \Drupal::service('entity.manager') drupal.org/node/2721791; and $entity_def->get() should become $entity_def->getKey(). Ideally also, if you're doing this in a form, you should avoid accessing \Drupal directly, and use dependency injection: code.tutsplus.com/tutorials/…
  • therobyouknow
    therobyouknow about 2 years
    +1 upvote - works perfectly with Drupal 9.3.3 from myself trying this out just now. Haven't tried the other examples yet, but I'll use this one for now.