
Upgrade Your Drupal Skills
We trained 1,000+ Drupal Developers over the last decade.
See Advanced Courses NAH, I know EnoughThese Are A Few of My Favorite Things - Drupal 7 Hooks Part 1

I still remember the first "Aha!" moment I had as a new Drupal developer. I had a node form that needed something or another changed on it, and I remember beating my head against template.php for hours until I finally broke down realized I may need to write a custom module to facilitate this change. At the time (which was like eight years ago), I was very much the Drupal n00b, and my experience with writing custom modules was very limited and relegated mostly to writing custom admin forms and the like. After what seemed like hours of scouring through API documentation and forum posts I saw that what I needed to do was implement something everyone was calling: hook_form_alter().
Eight years later and probably hundreds of thousands of lines of code later, I can't imagine my life as a Drupal developer without hooks. Hooks allow us to, well, "hook" into various parts of Drupal and override, change, or add to its behavior. I won't delve into exactly how hooks work, as that's another article, but suffice to say they make my life a lot simpler.
The move from D5 to D6 did not give us many more new hooks to work, but many existing hooks were improved upon. The advent of $form_state is one major improvement that comes to mind immediately. Well, in D7 hooks have gotten the love they deserve. Yes, there are a lot more hooks now, and yes, that means a larger core, but that also means more flexibility for module developers.
The first reason for the increase in the number of hooks from D6 to D7 is the separation of hooks with an $op parameter into their own hook implementations. D6 hooks such as hook_nodeapi(), hook_user(), and hook_comment() all took an $op parameter that we could use to operate on node, user, or comment objects at various points in their lifespan. Each $op parameter has now been split out into its own hook. For example, in D6's implementation of hook_nodeapi(), $op had the following possible values:
- alter
- delete
- delete revision
- insert
- load
- prepare
- prepare translation
- rss item
- search result
- presave
- update
- update index
- validate
- view
If you had a module that implemented hook_nodeapi() you probably became accustomed to having to write long switch statements that determined what to do depending on the current value of $op. For instance, this should look familiar:
<?php function mymodule_nodeapi(&$node, $op) { switch ($op) { case 'load': // do something when a node is loaded break; case 'insert': case 'update': // do something when a new is created or updated break; case 'delete': // do something when a node is deleted break } } ?>
While powerful, these hooks could get verbose fast. As stated, in D7, these separate $op values have now been split into their own hooks. So now, we have hooks like: hook_node_load(), hook_node_insert(), hook_node_update(), and hook_node_delete(). This is good as it means less overhead and less code. And I always hated having to write switch statements on $op.
Beyond refactoring some of D6's hooks, D7 gives a load of new hooks. In this article, I want to share a few of the ones that, I believe, are very exciting and will change the Drupal landscape, opening up a new arena of flexibility and features for module developers.
The first new D7 hook I saw that made me do a double-take was hook_page_alter(). Now, in D7, the theme layer has been refactored and pages are rendered from the information contained in an associative array: $page. An example of a $page array's top level elements should make this clearer:
<?php $page['page_top']; $page['header']; $page['sidebar_first']; $page['content']; $page['sidebar_second']; $page['page_bottom']; ?>
As you can see, the top level keys of the $page array correspond to regions. Each of these contain information that Drupal parses through to determine how a page should be rendered. With hook_page_alter(), we can dip into this array and make changes right before the $page array is sent to the theme layer. This is a boon for module developers and theme developers alike. The API documentation has a good example to illustrate what we can do with hook_page_alter():
<?php function hook_page_alter(&$page) { // Add help text to the user login block. $page['sidebar_first']['user_login']['help'] = array( '#weight' => -10, '#markup' => t('To post comments or add new content, you first have to log in.'), ); } ?>
Let's say you don't want to display links for a specific node type. Easy:
<?php $type = $page['content']['nodes'][$node->nid]['#bundle']; if ($type == 'article') { unset($page['content']['nodes'][$node->nid]['links']); } ?>
Get the idea? This is a HUGE win for Drupal, in my opinion, from a productivity perspective. This hook plays very nicely the related hook: hook_page_build(). hook_page_build(), as you might have guessed, allows module's to add elements to the page array BEFORE they are rendered. As as result, hook_page_alter() is called after hook_page_build().
This new power comes to us via Drupal's implementation of "renderable arrays". Basically, anything that will end up as HTML on a page begins its life as a structured array which contains data that informs Drupal of how it should parse it and render the data as HTML. We've seen this before in D6 with the Form API. Now our page content works on a similar principle. So, essentially, if you know how to manipulate an array, you should be able to bend Drupal to your will when it comes to content manipulation. Complex UI/UX-related business requirements should now be fairly straightforward to address in code, which means more time for themers to concentrate on the site's design and usability and not so much about having to write convoluted theme overrides to change seemingly simple page and content elements.
In the next article of this series we'll look at two more brand new Drupal 7 hooks that I'm salivating over trying out: hook_query_alter() and hook_query_TAG_alter().
Until next time, happy coding.
Further reading:
About Drupal Sun
Drupal Sun is an Evolving Web project. It allows you to:
- Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
- Facet based on tags, author, or feed
- Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
- View the entire article text inline, or in the context of the site where it was created
See the blog post at Evolving Web
