3

I'm using hook_form_FORM_ID_alter to modify the content of the form on the search page — I want to remove the "phrase" and "not" fields, and restrict the "only of the types" checkboxes to a hand selected list of types.

I have the following code, which is being called and which I think should work:

function MYMODULE_form_search_form_alter(&$form, &$form_state, $form_id) {
    unset($form['basic']);
    unset($form['advanced']['keywords']['phrase']);
    unset($form['advanced']['keywords']['negative']);
    unset($form['advanced']['type']);
    $form['advanced']['type'] = array(
        '#type' => 'checkboxes',
        '#title' => t('Only of the type(s)'),
        '#options' => array(
            'blog' => 'Blog entry',
            'event' => 'Event',
            'news' => 'News article'
        )
    );
    // print_r($form);
    // die;
}

Except node_form_search_form_alter gets to the search form after my form alter hook runs, so I don't get a chance to modify any of the form elements that it's adding.

I'm running Drupal 7.22.

How can I modify the advanced search form when my module hook runs before the hook that defines the advanced search form?

2 Answers 2

5

Changing the module weight will work, but sometimes that can cause problems with the order in which other hooks in your module are invoked.

Drupal provides hook_module_implements_alter() for exactly this sort of situation, so that you can target the order a specific hook is run in:

Alter the registry of modules implementing a hook.

This hook is invoked during module_implements(). A module may implement this hook in order to reorder the implementing modules, which are otherwise ordered by the module's system weight.

The code might look something like

function MYMODULE_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'form_alter') {
    // Move MYMODULE to the end of the list.
    $group = $implementations['MYMODULE'];
    unset($implementations['MYMODULE']);
    $implementations['MYMODULE'] = $group;
  }
}

Once you clear the cache your module's implementation of hook_form_alter() will be invoked last (unless of course another module is implementing hook_module_implements_alter() and altering the order again. But that's a different story).

I personally prefer this method as it's just a simple code change, no need to maintain any changes to the system table in the database.

I'm not sure how well that works with a form_FORM_ID_alter hook (never tried it), but with this method you can at least make sure that only the weight for hook_form_alter() need be updated.

Actually looking at the code for drupal_alter(), changing the conditional to if ($hook == 'form_search_form_alter') would probably work.

1
  • 1
    Thanks, that worked. The check needed to be against form_alter, not form_search_form_alter - don't know why, but the doco says the check always needs to be against the original hook (form_alter) and never the variant (form_search_form_alter).
    – George
    Commented Jul 8, 2013 at 0:29
1

Hooks are ordered by module's weight. Easiest way is to simply use Modules weight module and order them as you please:

We always need to modify modules execution order, and some could write a code that execute a query to modify the weight of a module in system table, some might go straight to his favorite SQL client and modfiy the record directly, This module provide admin interface for users/people has the access to modules page to reorder the module weights as they want, it provide a drag/drop functionality to order the contributed modules execution.

That's easy, but not portable. To make it more portable, use hook_install():

function your_module_name_install() {
  db_update('system')
    ->fields(array('weight' => your_preferred_weight))
    ->condition('name', '[your_module_name]', '=')
    ->execute();
}

or follow any other way outlined in the docs on Drupal.org.

2
  • Thanks for the answer, I wasn't aware that modules had weights before - I ended up going with the module_implements_alter hook because it seemed a little neater than changing the module weight.
    – George
    Commented Jul 8, 2013 at 0:31
  • @George it is neater, and at the same time more difficult. And only works for certain stages of execution (ie for sure you cannot alter order of hook_module_implements_alter with it). But yes, if it is sufficient and does not call for hacking modules, Clive's way seems safer. On the other hand, my custom modules are usually meant to be called last anyway, as they are tiding up what came from core and contrib. So I want all my hooks to get kicked at the end of their queues.
    – Mołot
    Commented Jul 8, 2013 at 6:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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