3

I'm trying to add a role to a user but I can't save the change.

function hook_entity_presave(Drupal\Core\Entity\EntityInterface $entity){
  $user = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());
  $user->addRole('foobar');
}

I would like to save the change, but $user->save() causes a fatal error.

What would be the correct way?

Note: The error is a whitescreen of death. I guess $user->save() is for creating new users. I would need to update an existing one.

2
  • Please update the question with the error you are getting.
    – Kevin
    Feb 10, 2017 at 15:15
  • 1
    There is a lot missing here - you should ensure you are about to operate on a User entity, and you should be loading the user from that entities provided id, not currentUser.
    – Kevin
    Feb 10, 2017 at 15:15

4 Answers 4

1

Code should look like this, as an example:

use Drupal\Core\Entity\EntityInterface;
use Drupal\user\Entity\User;

function mymodule_entity_presave(EntityInterface $entity) {
  if ($entity instanceof AccountInterface && $entity->isTranslatable()) {
    $user = User::load($entity->id());
    $user->addRole('foobar');
  }
}

Or better yet, hook_ENTITY_TYPE_presave():

use Drupal\Core\Entity\EntityInterface;
use Drupal\user\Entity\User;

function mymodule_user_presave(EntityInterface $entity) {
  $user = User::load($entity->id());
  $user->addRole('foobar');
}

Simply using hook_entity_presave will fire for any entity about to be saved. So you either need to check the incoming entity, or use the second hook to isolate it.

2
  • Unfortunatelly this is not working. I want to add a user role while creating new content. So the $entity wouldn't be a user. That's why I used $user = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id()); Also the _hook_user_presave isn't called.
    – J. Dough
    Feb 13, 2017 at 8:43
  • Looks like $user->save(); is missing? May 5, 2023 at 10:16
1

For the code shown in the question, notice that:

  • hook_entity_presave() is called before every entity is saved, including a view, a block, a contact form, or an image style (just to list a few entities Drupal core implements)

  • With \Drupal::currentUser()->id(), you are getting the ID of the currently logged-in user; in the case a user is creating an entity for another user, that code would not assign the new role to the right account, which I assume should be the user who created the entity

  • The code is not checking the user account is for the anonymous user; supposing that anonymous users are allowed to create an entity, that code would not work as expected, since anonymous users don't have roles assigned

For the rest, the correct code to assign a role to $user requires to call $user->addRole() and $user->save().

Since you want to assign the new role when a node is saved, I would rather use the following code.

use Drupal\Core\Entity\EntityInterface;
use Drupal\node\NodeInterface;
use Drupal\user\EntityOwnerInterface;
use Drupal\user\UserInterface;

/**
 * Implements hook_ENTITY_TYPE_presave() for nodes.
 */
function mymodule_node_presave(EntityInterface $entity) {
  if ($entity instanceof EntityOwnerInterface) {
    /** @var \Drupal\user\UserInterface $user */
    $user = User::load($entity->getOwnerId());
    $user->addRole('foobar');
    $user->save();
  }
}
1

I received an error using hook_user_presave saying unable to flip string and integer on $entity_id. Looks like it doesn't have the id on presave, worked when I switched to hook_user_insert.

<?php
use Drupal\Core\Entity\EntityInterface;
use Drupal\user\Entity\User;


function mymodule_user_insert(EntityInterface $entity) {
  $user = User::load($entity->id());
  $user->addRole('foobar');
  $user->save();
}
1
  • The OP said in a comment: Unfortunatelly this is not working. I want to add a user role while creating new content. So $entity wouldn't be a user. That's why I used $user = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());. Also hook_user_presave() isn't called.
    – apaderno
    Jul 26, 2018 at 16:06
0

I couldn't assign new roles in hook_entity_presave(). Maybe I just didn't find the right way to do it. Anyway, $entity->id() doesn't work for new users because the entity has not been saved yet, so there's no id...

My solution was to alter the registration form and add #default_values for the roles I needed to be automatically assigned for the new user.

For example, I needed the new users to be created with the role Client (client).

function hook_form_user_register_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  $form['account']['roles']['#access'] = FALSE;
  $form['account']['roles']['client'] = array(
      '#default_value' => TRUE,
      '#disabled' => TRUE,
    );
}

This way, there's no need to make any alterations in hook_entity_presave().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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