6

I want to create a single node of content type XYZ for each user upon registration.

I tried to use hook_user_insert() (hook_entity_insert()), but this doesn't work because when I set the nid to the uid, the uid is still 0 (anonymous user), and the node needs to be assigned to the newly created account. (NOTE: This was my misunderstanding, see below.)

I want to create the nodes upon account creation because each user should have only one node of this content type.

In Drupal 7, I managed to do this in Rules using a rule set in which I saved the user account and then created the new node. Since Rules isn't in beta for Drupal 8 yet, I am trying to do this programmatically.

Here is the code I am using:

function MYMODULE_user_insert(Drupal\Core\Entity\EntityInterface $entity) {
  $user = \Drupal::currentUser();
  $profile = Node::create(['type' => 'userprofilenode']);
  $profile->set('uid', $user->id());
  $profile->enforceIsNew();
  $profile->save();

As noted in 4k4's answer, $entity already has a UID. The problem is that I mistakenly introduced the current user, which is 0 (anonymous).

2
  • Did you try hook_entity_presave()? Something like this /** * Implements hook_entity_presave(). */ function my_module_entity_presave($entity) { if (($entity instanceof UserInterface) { $uid = $entity->id(); ... } else { return; } }
    – Rockabelly
    Oct 14 '17 at 11:10
  • Of course, you might need to check if it is a new user $entity->isNew() or/and if the user has a specific role $entity->hasRole($rid).
    – Rockabelly
    Oct 14 '17 at 14:00
11

In an insert hook the user is already saved and should have an user id. So creating a node and assigning it to the new user as author should be no problem:

/**
 * Implements hook_ENTITY_TYPE_insert() for user entities.
 *
 * Adds a first node for a new user
 */
function mymodule_user_insert(\Drupal\user\UserInterface $user) {
  \Drupal\node\Entity\Node::create([
    'type' => 'XYZ',
    'title' => 'First node for user #' . $user->id(),
    'uid' => $user->id(),
  ])->save();
}
1

This is very easy to do in D8 Rules. The advantage you get from using Rules is that you don't have to write code and it doesn't take a custom module or developer to change the action if your needs change in the future. In this way Rules is like Views - you can either program this functionality or you can make it available to the UI for easy building and maintaining.

Here is an export of a Rule which does what you asked - when a new user is created, it creates a new node (of type article, as an example). It then sets the node author to be the new user. It then sets a field of the new node (the body field, in this case) to a value take from the user (the user's email address, in this case). As you can see, Rules are stored in YAML files, and are imported/exported like any other configuration in D8. So you can just import this and you will immediately have a working example which you can then modify to use the specific fields you've defined on your user entity and node type. This Rule additionally displays a system message, which is a very useful way to debug Rules.

langcode: en
status: true
dependencies: {  }
id: create_a_node_for_each_new_user
label: 'Create a node for each new user'
events:
  -
    event_name: 'rules_entity_insert:user'
description: 'Node fields will be populated from values entered on the user form.'
tags: {  }
config_version: '3'
expression:
  id: rules_rule
  uuid: c9428f2d-c0b9-47bf-a7e5-3f2cc8af9f54
  conditions:
    id: rules_and
    uuid: 47b8d622-ed38-4977-8e58-4cca6d89260a
    conditions: {  }
  actions:
    id: rules_action_set
    uuid: d96fd6b5-1638-4b15-adde-5f5d7673fb8f
    actions:
      -
        id: rules_action
        uuid: e09cd52d-76fe-4682-91de-bfed58a651ab
        context_values:
          message: 'Node created using information entered by <em>{{ user.name }}</em> when registering'
          type: status
          repeat: false
        context_mapping: {  }
        context_processors:
          message:
            rules_tokens: {  }
          type:
            rules_tokens: {  }
          repeat:
            rules_tokens: {  }
        provides_mapping: {  }
        action_id: rules_system_message
      -
        id: rules_action
        uuid: fe2acb55-9234-4754-9d2b-3d1889d1775c
        context_values:
          type: article
          title: 'Article created by Rules for {{ user.name }}'
        context_mapping: {  }
        context_processors:
          type:
            rules_tokens: {  }
          title:
            rules_tokens: {  }
        provides_mapping: {  }
        action_id: 'rules_entity_create:node'
      -
        id: rules_action
        uuid: 743be03f-d1b7-4251-a1ac-80b17aa5c86e
        context_values:
          value: '{{ user.mail.value }}'
        context_mapping:
          data: entity.body
        context_processors:
          value:
            rules_tokens: {  }
        provides_mapping: {  }
        action_id: rules_data_set
      -
        id: rules_action
        uuid: 91f3c8f2-eb47-46e6-a9dd-2affc90e15d2
        context_values: {  }
        context_mapping:
          data: entity.uid.target_id
          value: user.uid.value
        context_processors: {  }
        provides_mapping: {  }
        action_id: rules_data_set

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.