I'm trying to change the label and field instructions for the name field on the User Account Creation form. I'm new to coding, and thought this would be an easy task.

My custom module is enabled and I've cleared caches, but none of my changes show up. Here is my code. I've tried a bunch of variations and a bunch of searching, but I never see a single sign of this working.


 * @file
 * Contains mymodule.module.

use Drupal\Core\Form\FormStateInterface;

 * Implements hook_form_FORM_ID_alter() on behalf of mymodule.module.
 * @see \Array method Array at Array
function mymodule_form_account_alter(&$form, FormStateInterface $form_state, $form_id) {
  // print_r($form); die;
  // ksm($form_id);
  if ($form_id == 'user_register_form') {
    // print_r($form); die;
    // kint($form_id);
    $form['name'] = array(
      '#type' => 'textfield',
      '#title' => $this->t('First and last name'),
      '#maxlength' => USERNAME_MAX_LENGTH,
      '#description' => $this->t("Rewrite this about spaces, periods (.), hyphens (-) and apostrophes (')."),
  drupal_set_message('mymodule_form_account_alter() executed.');

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!

  • Thanks - this works perfectly. I imagine you tested it to ensure all the details were correct, and that's much appreciated.
    – lacuna
    Jul 15 '18 at 0:51
  • :) it's a pretty standard alter .. but yes I've tested it
    – Kladrian
    Jul 15 '18 at 16:27

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.
  • I'd like to give you some piece of advices to learn how drupal works and how you can solve some of the issues you described in this note, but I don't think that a comment will be enough.
    – Kladrian
    Jul 15 '18 at 17:19

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.');.

  • thanks! the explanation is helpful. it seems the code is missing critical bits, but I greatly appreciate the thoughtful writeup. Between your answer and that of @Kladrian, I have a lot more clarity about hook_form_alter than before.
    – lacuna
    Jul 15 '18 at 0:54

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.