Is there a way to change the order of execution of hook_form_alter in Drupal 7 without changing a module's weight or hacking Drupal Core?

I am trying to alter the element added in translation_form_node_form_alter from the translation module. When debugging the form I can't find the element so I assume my hook is being executed before the one in the translation module is.

up vote 2 down vote accepted

I don't think so. translation_form_node_form_alter() implements hook_form_BASE_FORM_ID_alter() which I believe is called after hook_form_alter(), so even changing the module weight wouldn't be enough. I think your two options are to use a hook_form_BASE_FORM_ID_alter() and ensure you have a high enough module weight, or use hook_form_FORM_ID_alter() (if possible).

  • hook_form_FORM_ID_alter() IS called after hook_form_alter() – iStryker Jul 26 '11 at 12:56
  • Solved it using hook_form_form_id_alter and module weight. – Bart Jul 26 '11 at 13:22
  • @Bart if you used hook_form_FORM_ID_alter() then my understanding is that you shouldn't need to modify the weight at all (because all hook_form_FORM_ID_alter() calls are made after all hook_form_BASE_FORM_ID_alter()). – Andy Jul 26 '11 at 13:31
  • @Andy, it doesn't seem to work if I use foo_form_page_node_form_alter without adjusting the weight. – Bart Jul 26 '11 at 13:38
  • 1
    @Bart I was looking at the source to give you those details - check out the bottom of drupal_prepare_form() and drupal_alter(). I'd already noticed that the docs seemed off, so I created an issue. Dunno why it doesn't work for you without altering the system weight tho! – Andy Jul 26 '11 at 15:21

Also worth mentioning, there is a new drupal 7 API called hook_module_implements_alter() which lets you alter the execution order for a given hook WIHOUT altering the module weights table.

Sample code from the API docs showing how easy this is to do:

<?php
function hook_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'rdf_mapping') {
    // Move my_module_rdf_mapping() to the end of the list. module_implements()
    // iterates through $implementations with a foreach loop which PHP iterates
    // in the order that the items were added, so to move an item to the end of
    // the array, we remove it and then add it.
    $group = $implementations['my_module'];
    unset($implementations['my_module']);
    $implementations['my_module'] = $group;
  }
}
?>
  • I was able to execute my hook last with this exact code. Thanks! – Beau Oct 26 '17 at 20:16

Here is how to make sure your hook_form_alter is called after another modules hook_form_alter:

/**
 * Implements hook_form_alter().
 */
function my_module_form_alter(&$form, &$form_state, $form_id) {
  // do your stuff
}

/**
 * Implements hook_module_implements_alter().
 *
 * Make sure that our form alter is called AFTER the same hook provided in xxx
 */
function my_module_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'form_alter') {
    // Move my_module_rdf_mapping() to the end of the list. module_implements()
    // iterates through $implementations with a foreach loop which PHP iterates
    // in the order that the items were added, so to move an item to the end of
    // the array, we remove it and then add it.
    $group = $implementations['my_module'];
    unset($implementations['my_module']);
    $implementations['my_module'] = $group;
  }
}

This also works when the other module has provided a form_alter hook in the variation: hook_form_FORM_ID_alter. (they explain that in the documentation: hook_module_implements_alter).

I know that this post is quite similar to wiifm's post, but thought it useful with an example with hook_form_alter

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.