My objective: Let say there is a role named "author". I would like to have a registration form having this path: /register/author, when the user submit, he/she will get the author role (same for any other roles like /register/another_role)

Here is what I have done:

1-Creating a route: last argument will be the role name

  path: '/register/{role}'
    _form: 'Drupal\mymodule\Form\RegisterByRole'
    _title: 'Register by role'
    _permission: 'access content'

2-Extending the RegisterForm Class

class RegisterByRole extends RegisterForm
    public function form(array $form, FormStateInterface $form_state, $role = null)
        $form = parent::form($form, $form_state);
        if (role_is_allowed($role)) {
            $form['test'] = [
                '#markup' => '<p>Test:' . $role
        return $form;

Of course I must change the submit function to assign the role, but I already have the following error when visiting the /register/author path:

Error: Call to a member function getEntityTypeId() on null in Drupal\Core\Entity\EntityForm->getBaseFormId() (line 111 of core/lib/Drupal/Core/Entity/EntityForm.php).

I found that if I add the __construct and the create functions in the RegisterByRole class definition, the getBaseFormId error disappears... But I don't understand why?... And more annoying, I couldn't get the value of my $role argument (last arg of the route).

What is wrong in my plan?

  • Instead of a form route you could use a controller with a route parameter for the role, create a new user, add the role to the newly created user and then build the entity form with it by hand, see drupal.stackexchange.com/questions/230527/…
    – 4uk4
    Commented Mar 12, 2020 at 7:20
  • Many thanks for your comment, I could solve this issue by adding an _entity_form like explained by Jaypan. I think you idea is also nice... As requested by Jaypan, I will create a new Q&A for the remaining problem which is the role parameter not transmitted to the form.
    – Baud
    Commented Mar 12, 2020 at 8:31
  • You've asked for a plan. For entity forms the best place to transport initial values is the entity itself.
    – 4uk4
    Commented Mar 12, 2020 at 8:39
  • Thank you... I have to say that I don't undersand very well what you are saying: "transport initial values by the entity"... I have created a new Q&A for this topic as asked by Jaypan: drupal.stackexchange.com/questions/291874/…
    – Baud
    Commented Mar 12, 2020 at 8:51
  • 1
    My plan is instead of transmitting the value to the form add it to the entity $user->addRole($role); and pass the entity to the form as shown in the linked question.
    – 4uk4
    Commented Mar 12, 2020 at 9:20

1 Answer 1


I believe the problem is here:

_form: 'Drupal\mymodule\Form\RegisterByRole'

You need to use _entity_form rather than _entity, as the RegisterForm is actually an entity form for the User entity, as described in the Entity declaration for \Drupal\user\Entity\User:

"form" = {
  "register" = "Drupal\user\RegisterForm"

But to do this, you'll have to register a new form op for that class. You can do this in hook_entity_type_alter():

function hook_entity_type_alter(array &$entity_types) {
  $user = &$entity_types['user'];
  $user->setFormClass('role_registration', 'Drupal\example\Form\RegisterByRole');

Then, back in your route, you'll remove _form and instead implement_entity_form, setting it to to user.role_registration:

_entity_form: 'user.role_registration'
  • I feel like it's a good lead, but I don't know what to do: Should I replace "_form" by "_entity_form"? I am not sure, because, when doing this, I got this error: "RegisterByRole" entity type does not exist.
    – Baud
    Commented Mar 11, 2020 at 18:15
  • Sorry, my post needs more info, but I have no time to updated it now. I'll do it when I can. But you need to set the _entity_form something like 'user.role_register', then you will need to implement hook_entity_type_alter() and implement setFormClass() on the user type, passing the op as 'role_register' and your class as the value. I'll give some code later.
    – Jaypan
    Commented Mar 11, 2020 at 18:21
  • I think I understand... The plan is to use my RegisterByRole's class for all register process (with setFormClass() )... It was not my first idea, but I hope it will work...
    – Baud
    Commented Mar 11, 2020 at 18:40
  • Updated but not yet confirmed.
    – Jaypan
    Commented Mar 11, 2020 at 18:47
  • Many thanks! This working... except that the $role parameter is not populated/working. I have also a question : why using hook_entity_type_alter and not hook_entity_type_build? (I have tried: both are working)
    – Baud
    Commented Mar 11, 2020 at 23:58

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.