2

Is it possible to register hooks dynamically? I.e. not by hardcoding the hook handler into your code.

For instance, I'm writing a module and would like to add an option to some content type creation pages. I know this can be done using the hook_form_FORM_ID_alter hook, but since I don't know what node types will exist in the drupal installation I obviously can't hardcode the hooks.

Or will I have to use hook_form_alter or hook_form_BASE_FORM_ID_alter and check whether the option should be shown for that form? I'd really, REALLY would want to avoid that, since it's a really icky solution.

Or am I approaching this the wrong way?

  • I guess you should implement hook_form_BASE_FORM_ID_alter and make checks in it. Where is hook_module_implements_alter but it works with all module form_alter hooks as with one hook so it can't help. – kalabro Dec 14 '12 at 10:31
  • Hmmm, yes that's what I was afraid of. I really hope they'll dump this extremely crappy hooking system in future drupal versions. But doesn't seem like it. – Creynders Dec 14 '12 at 10:38
  • A lot of OOP stuff has been added in Drupal 8. We can make it better :) – kalabro Dec 14 '12 at 11:13
1

What you describe is what Drupal does in translation_form_node_form_alter(), and book_form_node_form_alter(). Both the hooks are implementations of hook_form_BASE_FORM_ID_alter() which first verify if the form should be modified.

Hooks are normal functions; to dynamically add them you should execute code similar to the following one, outside any function.

$body = "The body of the function";

foreach (mymodule_get_content_types() as $type) {
  eval("function mymodule_form_{$type}_alter { {$body} }");
}

That code would be executed every time the module file is loaded, and there would not be any practical benefit from using such code.

Considering that Drupal 8 will use Symfony, and its Dependency Injection Container, it is preferable to use hook_form_BASE_FORM_ID_alter() until Drupal 8, and then changing implementation with Drupal 8. (Module's code already needs to be changed for Drupal 8, anyway.)

  • Maybe I'm mistaken but it looks to me that having a pre-hook hook which allows you to map a hook to another function name would suffice. Something like: gist.github.com/4291816 – Creynders Dec 15 '12 at 6:59
  • You can simply use hook_form_alter(). What you propose just changes the name of the function implementing the hook; the function still needs a $form_id parameter like hook_form_alter() does. It doesn't seem that implementing such code is worth doing it. – kiamlaluno Dec 15 '12 at 12:15
  • I respectfully don't agree, the difference would be that it isn't called for every node type. (And in my specific case, I wouldn't need to check formid, since it'd be the same check for all subscribed nodetypes) In general it provides you with far more granular control on when a hook is called and therefore wastes less resources. And, no offense, but it's really a horrible practice calling a function in all cases, while you only need it in some. – Creynders Dec 15 '12 at 12:32
  • And TBH, not having to stuff your modules with those hideous, illegible hooks would be worth the trouble already. For instance scoga_form_nodetype_wished_item_node_form_alter Seriously. Any decent sized module is filled with a bunch of those. They make my eyeballs bleed. – Creynders Dec 15 '12 at 12:45
1

The usual approach is to create a settings form for your module and save the content types on which you want your hook_form_alter to intervene. Then with a simple check you can implement you alterations. The list of content types existing at a certain point in Drupal is easy to check.

I see no other way of actually placing your alters for specific content types. Even if you create your hook dynamically by using an unorthodox

foreach ($SELECTED_NODETYPES as $NODETYPE) {
  if (!function_exists("my_module_form_$NODETYPE_node_form_alter")) {
    function my_module_form_$NODETYPE_node_form_alter (&$form, &$form_state) {
        //your alterations
    }
  }
} 

You will still have to have a list of nodetypes to check from, and on each new nodetype creation you have to be sure you flush the cache so your module will declare the new hooks and Drupal actually will take them into account.

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.