Drupal 7 Blocks: What's Changed Under the Covers

Blocks in Drupal 6 (and 5) always felt a little less loved than other portions of Drupal. While the node and theming APIs offered straightforward and often elegant methods to modify behaviour without modifying other peoples' code, blocks weren't so fortunate. Lacking API support, working with blocks often meant writing ugly code. Last week helping with the Drupal Block API documentation I discovered this has changed in Drupal 7. I thought I'd share what I learned.

The information I'll discuss is a summary of the block information from:

hook_block() has been split up

The Drupal 7 Block API's most noticeable change is the splitting of hook_block():

Hopefully gone are those sometimes awkward select statements.

Hook Alters

The Drupal 7 Block API now has alter hooks! These new hook provide a clean way to modify other blocks in the system:

  • hook_block_info_alter()
    This hook allows you to change a block definition before it's saved to the database.
  • hook_block_list_alter()
    This hook allows you to add, remove or modify block definitions in the block list. This happen before the blocks are rendered, so you can even override the contents of the block. This hook can replace the use of db_rewrite_sql() or hook_query_alter() for altering the blocks list.
  • hook_block_view_alter()
    This hook allows you to modify the contents of any block returned by hook_block_view().
  • hook_block_view_MODULE_DELTA_alter
    A convenience hook of sorts, this hook allows you modify the contents of a specific block rather than implementing hook_block_view_alter() and testing every call for the block of interest.

$delta module ID is text

The unique block ID within a module is known as the block "delta" and it's now a string instead of an integer. Blocks can now be given meaningful names. For example, instead of being identified as 1, a block might be identified as "index" or "groups". CSS classes and theming suggestions use this name as well, improving readability.

If you are a module maintainer be sure to read the notes on updating your block configuration from Drupal 6 to Drupal 7. There's a helper function provided.

Renderable Arrays as Output

Blocks should now return their output as renderable arrays. For example:

$block['content'] = array('#markup' => t('This is my string of text to display'));

This is part of an overall Drupal 7 change and not specific to blocks. Strings will continue to work, but a renderable array is strongly recommended.

Database Table Changes

The block tables have been renamed:

  • 'blocks' renamed to 'block'
  • 'blocks_roles' renamed to 'block_role'
  • 'boxes' renamed to 'block_custom'

Block Module Optional

Although enabled by default, the block module is not required and can be disabled. If you write code that relies on the block module be sure to declare it as a dependency in your module .info file or wrap the code in a statement that verifies the block module is enabled. For example: if (module_exists('block')) {...}

Permission String Change

The permission string "use PHP for settings" is replaced by "use PHP for block visibility".

Cache Constants Renamed

The BLOCK_CACHE_ prefix for cache constants is now DRUPAL_CACHE_.

See http://api.drupal.org/api/function/hook_block_info/7 for the list of constants.

Thanks

A big thank you to everyone who updated the code and documentation. Drupal 7 blocks have come a long way thanks to your effort!

Comments

There was a mistake in the example for "Renderable Arrays as Output". It's been corrected. My thanks to mikeytown2 for pointing that out.

Ok, $delta could be a string or integer in Drupal 6. Most of the Drupal 6 API examples show it as an integer. The notes on the "Converting 6.x modules to 7.x" definitely make it seem like string is a new thing, so I'm not sure what the deal is. Trying to track it down.

=> is shown as =>

Thanks. Fixed. The result of wrapping the example in code tags after proof-reading.

Glad you caught that deltas could be strings in Drupal 6, but Drupal core itself used integers. Strings are highly recommended because they make Drupal entities easier to export and because the delta will be used in the block ID in HTML. #block-user-login is so much nicer in our CSS than #block-user-0 (yep, that's the login block in Drupal 6).

Thanks for the explanation Benjamin! I'll update the paragraph when I get a chance.

Credit goes to Mikeytown2 for catching the Drupal 6 strings error.