How do I programmatically create a node?
Asked Answered
F

5

15

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?

Feudalism answered 11/6, 2014 at 21:21 Comment(3)
See entity_create()Slicer
@Slicer entity_create() will be removed in Drupal 9 according to your link. Better use the object way : Entity::create() or Node::create() for a node.Manx
@Manx Yep that's true. They weren't deprecated when I wrote the comment though, they were shiny and new ;)Slicer
F
2

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();
Feudalism answered 12/6, 2014 at 16:18 Comment(2)
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.Dinny
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/1895Ahearn
D
22
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();
Drubbing answered 5/8, 2015 at 4:56 Comment(0)
J
7

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();
Joacimah answered 8/3, 2016 at 17:31 Comment(2)
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/…Irrevocable
The big question for me is: how the structure of the node_array has to look like? If we use \Drupal::entityTypeManager()->getStorage('node')->load(NID) to show us the structure, it's only usefull to find out what the field names are.Ai
K
6

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

  $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'.

Kaleidoscope answered 18/11, 2014 at 22:36 Comment(0)
E
4

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();
Epicurus answered 17/10, 2018 at 14:38 Comment(1)
+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.Telepathy
F
2

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();
Feudalism answered 12/6, 2014 at 16:18 Comment(2)
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.Dinny
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/1895Ahearn

© 2022 - 2024 — McMap. All rights reserved.