Hook soup
Of late, I seem to keep stumbling upon Drupal hooks that I've never heard of before. For example, I was just reading a blog post about what you can't modify in a _preprocess()
function, when I saw mention of hook_theme_registry_alter()
. What a mouthful. I ain't seen that one 'til now. Is it just me, or are new hooks popping up every second day in Drupal land? This got me wondering: exactly how many hooks are there in Drupal core right now? And by how much has this number changed over the past few Drupal versions? Since this information is conveniently available in the function lists on api.drupal.org, I decided to find out for myself. I counted the number of documented hook_foo()
functions for Drupal core versions 4.7, 5, 6 and 7 (HEAD), and this is what I came up with (in pretty graph form):
And those numbers again (in plain text form):
- Drupal 4.7: 41
- Drupal 5: 53
- Drupal 6: 72
- Drupal 7: 183
Aaaagggghhhh!!! Talk about an explosion — what we've got on our hands is nothing less than hook soup. The rate of growth of Drupal hooks is out of control. And that's not counting themable functions (and templates) and template preprocessor functions, which are the other "magically called" functions whose mechanics developers need to understand. And as for hooks defined by contrib modules — even were we only counting the "big players", such as Views — well, let's not even go there; it's really too massive to contemplate.
In fairness, there are a number of good reasons why the amount of hooks has gone up so dramatically in Drupal 7:
- Splitting various "combo" hooks into a separate hook for each old
$op
parameter, the biggest of these being the death ofhook_nodeapi()
- The rise and rise of the
_alter()
hooks - Birth of fields in core
- Birth of file API in core
Nevertheless, despite all these good reasons, the number of core hooks in HEAD right now is surely cause for concern. More hooks means a higher learning curve for people new to Drupal, and a lot of time wasted in looking up API references even for experienced developers. More hooks also means a bigger core codebase, which goes against our philosophy of striving to keep core lean, mean and super-small.
In order to get a better understanding of why D7 core has so many hooks, I decided to do a breakdown of the hooks based on their type. I came up with the "types" more-or-less arbitrarily, based on the naming conventions of the hooks, and also based on the purpose and the input/output format of each hook. The full list of hooks and types can be found further down. Here's the summary (in pretty graph form):
And those numbers again (in plain text form):
Type | No. of hooks |
---|---|
misc action | 44 |
info | 30 |
alter | 27 |
delete | 20 |
insert | 13 |
load | 12 |
update | 10 |
validate | 6 |
form | 4 |
misc combo | 4 |
prepare | 4 |
view | 4 |
presave | 3 |
check | 2 |
As you can see, most of the hooks in core are "misc action" hooks, i.e. they allow modules to execute arbitrary (or not-so-arbitrary) code in response to some sort of action, and that action isn't covered by the other hook types that I used for classification. For the most part, the misc action hooks all serve an important purpose; however, we should be taking a good look at them, and seeing if we really need a hook for that many different events. DX is a balancing act between flexibility-slash-extensibility, and flexibility-slash-extensibility overload. Drupal has a tendency to lean towards the latter, if left unchecked. Also prominent in core are the "info" and "alter" hooks which, whether they end in the respective _info
or _alter
suffixes or not, return (for info) or modify (for alter) a more-or-less non-dynamic structured array of definitions. The DX balancing act applies to these hooks just as strongly: do we really need to allow developers to define and to change that many structured arrays, or are some of those hooks never likely to be implemented outside of core?
I leave further discussion on this topic to the rest of the community. This article is really just to present the numbers. If you haven't seen enough numbers or lists yet, you can find some more of them below. Otherwise, glad I could inform you.
Hooks in Drupal 4.7 core
- hook_access
- hook_auth
- hook_block
- hook_comment
- hook_cron
- hook_db_rewrite_sql
- hook_delete
- hook_elements
- hook_exit
- hook_file_download
- hook_filter
- hook_filter_tips
- hook_footer
- hook_form
- hook_form_alter
- hook_help
- hook_info
- hook_init
- hook_insert
- hook_install
- hook_link
- hook_load
- hook_menu
- hook_nodeapi
- hook_node_grants
- hook_node_info
- hook_perm
- hook_ping
- hook_prepare
- hook_search
- hook_search_preprocess
- hook_settings
- hook_submit
- hook_taxonomy
- hook_update
- hook_update_index
- hook_update_N
- hook_user
- hook_validate
- hook_view
- hook_xmlrpc
Hooks in Drupal 5 core
- hook_access
- hook_auth
- hook_block
- hook_comment
- hook_cron
- hook_db_rewrite_sql
- hook_delete
- hook_disable
- hook_elements
- hook_enable
- hook_exit
- hook_file_download
- hook_filter
- hook_filter_tips
- hook_footer
- hook_form
- hook_forms
- hook_form_alter
- hook_help
- hook_info
- hook_init
- hook_insert
- hook_install
- hook_link
- hook_link_alter
- hook_load
- hook_mail_alter
- hook_menu
- hook_nodeapi
- hook_node_access_records
- hook_node_grants
- hook_node_info
- hook_node_operations
- hook_node_type
- hook_perm
- hook_ping
- hook_prepare
- hook_profile_alter
- hook_requirements
- hook_search
- hook_search_preprocess
- hook_submit
- hook_taxonomy
- hook_uninstall
- hook_update
- hook_update_index
- hook_update_last_removed
- hook_update_N
- hook_user
- hook_user_operations
- hook_validate
- hook_view
- hook_xmlrpc
Hooks in Drupal 6 core
- hook_access
- hook_actions_delete
- hook_action_info
- hook_action_info_alter
- hook_block
- hook_boot
- hook_comment
- hook_cron
- hook_db_rewrite_sql
- hook_delete
- hook_disable
- hook_elements
- hook_enable
- hook_exit
- hook_file_download
- hook_filter
- hook_filter_tips
- hook_flush_caches
- hook_footer
- hook_form
- hook_forms
- hook_form_alter
- hook_form_FORM_ID_alter
- hook_help
- hook_hook_info
- hook_init
- hook_insert
- hook_install
- hook_link
- hook_link_alter
- hook_load
- hook_locale
- hook_mail
- hook_mail_alter
- hook_menu
- hook_menu_alter
- hook_menu_link_alter
- hook_nodeapi
- hook_node_access_records
- hook_node_grants
- hook_node_info
- hook_node_operations
- hook_node_type
- hook_perm
- hook_ping
- hook_prepare
- hook_profile_alter
- hook_requirements
- hook_schema
- hook_schema_alter
- hook_search
- hook_search_preprocess
- hook_system_info_alter
- hook_taxonomy
- hook_term_path
- hook_theme
- hook_theme_registry_alter
- hook_translated_menu_link_alter
- hook_translation_link_alter
- hook_uninstall
- hook_update
- hook_update_index
- hook_update_last_removed
- hook_update_N
- hook_update_projects_alter
- hook_update_status_alter
- hook_user
- hook_user_operations
- hook_validate
- hook_view
- hook_watchdog
- hook_xmlrpc
Hooks in Drupal 7 core
(D7 list accurate as of 17 Jun 2009; type breakdown for D7 list added arbitrarily by yours truly)