Drupal - Alter the user registration form

Here is the right code:

/**
 * Implements hook_form_FORM_ID_alter().
 */
function <your_module>_form_user_register_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  $form['account']['name']['#title'] = t('First and last name');
  $form['account']['name']['#description'] = t("Rewrite this about spaces, periods (.), hyphens (-) and apostrophes (').");
}

feel free to ask :) have fun!


Notes to self on lessons learned

Here's where I ran into problems

  • Hook names are very unintuitive.
  • Form IDs can be tough to get right.
  • Boilerplate can become out of date.

Here's how I can improve

When using boilerplate

  • Continue to use Drupal Console for boilerplate.
  • However, before committing to it for long-term use, or if something doesn't work, check api.drupal.org.
  • Seems this precaution could get very tedious, but may still be best approach for learners.

When deciphering hook names

  • Carefully determine what part of the name is the 'token' to replace.
  • Then carefully replace just that part.
  • As long as something in the hook name is wrong, you will stay blocked, so double- and triple-check.
  • In this case, the token was in all caps. See it in the comment provided by the boilerplate.
  • The lower case instance of 'form' needed to be preserved.

When determining form IDs

  • It would appear the only reliable source for form IDs is inspecting the rendered form html.
  • The form ID is (logically) contained within the <form> opening tag.
  • As long as something in the form ID is wrong, you will stay blocked, so double- and triple-check.
  • In this case, I thought the form ID came from the object as written in AccountForm.php and tried variations based on that assumption. When looking at explanations and examples online, I somehow stuck with that assumption and never got the correct ID.

Remaining challenges

  • Getting a printout of values - none of what I tried worked: kint(), dsm(), print_r($form); die;. This piece shouldn't be too hard once I find good documentation.
  • Understanding how the nested object gets called correctly. There's probably a good explanation out there.
  • Fixing Drupal documentation. This piece is complex.

The reason you aren't seeing any change in the user registration form is that the hook_form_FORM_ID_alter() for the user_register_form form has the wrong name.
Instead of mymodule_form_account_alter(&$form, FormStateInterface $form_state, $form_id) (which supposes it is being defined for a module whose machine name is mymodule), it should be mymodule_form_user_registration_form_alter(&$form, FormStateInterface $form_state, $form_id).
Alternatively, you could implement hook_form_alter() with the mymodule_form_alter() function. In this case, checking the form ID would be correct, as the hook would be invoked for each form used by Drupal.

Fixed the hook name, there are still errors in the code you are showing.

  1. Inside a function $this doesn't have any value/meaning. Only a class method that isn't static can use $this.

  2. A line like if ($form_id == 'user_register_form') is not necessary for mymodule_form_user_registration_form_alter(), since that hook is invoked for that form, and not any form a Drupal module is using.

  3. If you need to change some of the properties of a form element, you don't use $form['name'] = array( /* .... */); which is removing all the properties of that form element and adding only the ones you add to the array.

  4. The form field for the username, used in the account registration form, is $form['account']['name'], not $form['name'].

The correct code would be similar to the following one.

function mymodule_form_user_register_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $form['account']['name']['#title'] = new TranslatableMarkup('First and last name');
  $form['account']['name']['#description'] = new TranslatableMarkup("Rewrite this about spaces, periods (.), hyphens (-) and apostrophes (').");
}

Notice that:

  • While $form_id is one of the parameters passed to the hook, you don't need it to understand for which form the hook is invoked. Actually, I cannot think of any reason for hook_form_FORM_ID_alter() to use that parameter, except in the case the form ID must be concatenated to another string. (In that case, I would use $form_id . 'another string'.) This means the last hook parameter can also be omitted, since the code isn't using it.

    function mymodule_form_user_register_form_alter(&$form, FormStateInterface $form_state) {
      $form['account']['name']['#title'] = new TranslatableMarkup('First and last name');
      $form['account']['name']['#description'] = new TranslatableMarkup("Rewrite this about spaces, periods (.), hyphens (-) and apostrophes (').");
    }
    
  • I used the TranslatableMarkup class to output a translated string, which is Drupal 8 suggested class to use in this case, but you could use t() which is a function Drupal 9 still implements.

  • If you are testing when a hook is invoked, don't use drupal_set_message() (which is also a deprecated function). Use the Drupal logger, for example with a line like \Drupal::logger('mymodule')->notice('mymodule_form_account_alter() executed.');.

Tags:

Forms

8