0

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

mymodule.register:
  path: '/register/{role}'
  defaults:
    _form: 'Drupal\mymodule\Form\RegisterByRole'
    _title: 'Register by role'
  requirements:
    _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/… – 4k4 Mar 12 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 Mar 12 at 8:31
  • You've asked for a plan. For entity forms the best place to transport initial values is the entity itself. – 4k4 Mar 12 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 Mar 12 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. – 4k4 Mar 12 at 9:20
2

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'
| improve this answer | |
  • 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 Mar 11 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 Mar 11 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 Mar 11 at 18:40
  • Updated but not yet confirmed. – Jaypan Mar 11 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 Mar 11 at 23:58

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.