Overview
Sometimes Drupal installations need to have specific tasks performed upon the registration of different types of users. For example, most Drupal sites have multiple user roles, with these roles being applied to accounts by administrators, post account creation. An example of this would be a site that connects people with service providers for a given service. Service providers must provided with the role Service Provider
to be able to act as a service provider on the site.
In an out-of-the-box Drupal installation, users would self-register through the standard Drupal registration form, and an admin would apply the Service Provider
role, post-registration. This tutorial will explain how to create a separate registration form that applies the Service Provider
role to the newly created account upon registration without the necessity of an admin doing so. The steps this tutorial will cover are as follows:
- Extend the existing registration form to create a new registration form for service providers (code)
- Add the
Service Provider
role to the new user upon form submission (code) - Create a new form mode for users (UI)
- Tell the system to use the form from step 1, for the form mode from step 2 (code)
- Create a new route that uses the new registration form mode (code)
Required Knowledge
To follow this tutorial, you will need an understanding of Drupal site-building, how to create custom Drupal modules, and how to work with the Form API.
Step 1: Extend the existing registration form
The first step is to extend Drupal core's RegisterForm, to create a new form that service providers will use to register. [MODULE]/src/Form/ServiceProviderRegisterForm.php
:
<?php declare(strict_types=1); namespace Drupal\[MODULE]\Form; use Drupal\user\RegisterForm; /** * Extension of the default registration form, for registering service providers. */ class ServiceProviderRegisterForm extends RegisterForm { /** * {@inheritdoc} */ public function getFormId() { return 'service_provider_register_form'; } }
Step 2: Add the Service Provider
role to the new user upon form submission
The base RegisterForm
form will handle the creation of the user and almost everything under the hood. All that needs to be handled in the custom extended form is to add the role to the user entity before the user entity is saved. This is done by overriding the save()
method of the RegisterForm
, adding the Service Provider
role to the user before handing off to the parent for saving:
/** * {@inheritdoc} */ // First, retrieve the user object. /** @var \Drupal\user\UserInterface */ $account = $this->entity; // Add the role to the account using the role machine name. $account->addRole('service_provider'); // Pass off the rest of the submission to the parent. The parent // will save the user entity. parent::save($form, $form_state); }
Step 3: Create a new form mode for users
Next, in the user interface, navigate to Admin -> Structure -> Display Modes -> Form Modes -> Add Form Mode. Click 'User' to add a new form mode to users. For the name enter Service Provider Registration Form, and user Enable this form for the following User types, check the User checkbox. Finally, click Save:
Now, the newly created form can be managed through the UI as an entity form at Admin -> Configuration -> People -> Account Settings -> Manage Form Display -> Service Provider Registration Form. The machine name of the new form mode can then be retrieved from the URL, and will likely be service_provider_register_form
.
Step 4: Tell the system to use the new form
Now that a registration form has been created (step 1) and a form mode created (step 3), the next step is to connect the registration form to that form mode. This is done by implementing hook_entity_type_build().
use Drupal/[MODULE]/Form/ServiceProviderRegisterForm; /** * Implements hook_entity_type_build(). */ // Use the machine name of the form mode for the first argument, // and the fully namespaced class for the second argument. $entity_types['user']->setFormClass('service_provider_registration_form', ServiceProviderRegisterForm::class); } }
Step 5: Create a new route that uses the new registration form mode
The final step is to create a new route at which the new form can be accessed:
# This is an arbitrary key that should be prefixed with the module name [MODULE].service_provider.registration: path: /service-provider-sign-up defaults: # This should be [ENTITY TYPE].[FORM MODE]. _entity_form: 'user.service_provider_register_form' _title: 'Register as a service provider' requirements: _access_user_register: 'TRUE'
With this, anonymous users will now be able to register at the path /service-provider-sign-up
.
Summary
This tutorial explained how to create a role-specific registration form, by extending the Drupal core registration form, creating a new form mode that uses this form, and creating a custom route at which the user can register. When the user completes the form, their new account automatically has the Service Provider
role applied. While this tutorial explained how to add a role upon submission, this method could be used for any type of specialized registration form on a Drupal site, such as a type of registration that requires programmatically creating some content upon account creation, or pinging a remote API. Any of these can be handled in the save()
method of the RegisterForm
, in the same manner that the role was added in this tutorial.
Complete Code
[MODULE]/src/Form/ServiceProviderRegisterForm.php
:
<?php declare(strict_types=1); namespace Drupal\[MODULE]\Form; use Drupal\user\RegisterForm; /** * Extension of the default registration form, for registering service providers. */ class ServiceProviderRegisterForm extends RegisterForm { /** * {@inheritdoc} */ public function getFormId() { return 'service_provider_register_form'; } /** * {@inheritdoc} */ // First, retrieve the user object. /** @var \Drupal\user\UserInterface */ $account = $this->entity; // Add the role to the account using the role machine name. $account->addRole('service_provider'); // Pass off the rest of the submission to the parent. The parent // will save the user entity. parent::save($form, $form_state); } }
in [MODULE].module
:
use Drupal/[MODULE]/Form/ServiceProviderRegisterForm; /** * Implements hook_entity_type_build(). */ // Use the machine name of the form mode for the first argument, // and the fully namespaced class for the second argument. $entity_types['user']->setFormClass('service_provider_registration_form', ServiceProviderRegisterForm::class); } }
[MODULE].routing.yml
:
# This is an arbitrary key that should be prefixed with the module name [MODULE].service_provider.registration: path: /service-provider-sign-up defaults: # This should be [ENTITY TYPE].[FORM MODE]. _entity_form: 'user.service_provider_register_form' _title: 'Register as a service provider' requirements: _access_user_register: 'TRUE'