7.x block.api.php hook_block_list_alter(&$blocks)

Act on blocks prior to rendering.

This hook allows you to add, remove or modify blocks in the block list. The block list contains the block definitions, not the rendered blocks. The blocks are rendered after the modules have had a chance to manipulate the block list.

You can also set $block->content here, which will override the content of the block and prevent hook_block_view() from running.


$blocks: An array of $blocks, keyed by the block ID.

Related topics

4 functions implement hook_block_list_alter()

Note: this list is generated by pattern matching, so it may include some functions that are not actually implementations of this hook.

block_block_list_alter in modules/block/block.module
Implements hook_block_list_alter().
dashboard_block_list_alter in modules/dashboard/dashboard.module
Implements hook_block_list_alter().
node_block_list_alter in modules/node/node.module
Implements hook_block_list_alter().
overlay_block_list_alter in modules/overlay/overlay.module
Implements hook_block_list_alter().
1 invocation of hook_block_list_alter()
_block_load_blocks in modules/block/block.module
Loads blocks' information from the database.


modules/block/block.api.php, line 333
Hooks provided by the Block module.


function hook_block_list_alter(&$blocks) {
  global $language, $theme_key;

  // This example shows how to achieve language specific visibility setting for
  // blocks.
  $result = db_query('SELECT module, delta, language FROM {my_table}');
  $block_languages = array();
  foreach ($result as $record) {
    $block_languages[$record->module][$record->delta][$record->language] = TRUE;
  foreach ($blocks as $key => $block) {

    // Any module using this alter should inspect the data before changing it,
    // to ensure it is what they expect.
    if (!isset($block->theme) || !isset($block->status) || $block->theme != $theme_key || $block->status != 1) {

      // This block was added by a contrib module, leave it in the list.
    if (!isset($block_languages[$block->module][$block->delta])) {

      // No language setting for this block, leave it in the list.
    if (!isset($block_languages[$block->module][$block->delta][$language->language])) {

      // This block should not be displayed with the active language, remove
      // from the list.


Rob230’s picture

It seems that most implementations use unset(). For example, the node module. If my module runs before it then the node module will simply remove blocks that I wanted to keep. If my module runs after it then the node module will have already removed blocks from the array and I can't add them back unless I repeat the query of _block_load_blocks() which invokes this hook.

nidaismailshah’s picture

As far as i have understood if there is a single module that wouldn't want the block to appear, the block wouldn't be visible. It follows the logical AND operator logic. and if you don't want the node module to restrict it, change the settings at the add/ edit block page. there is no point in overriding.

nvahalik’s picture

If you are wanting to rearrange blocks on the page and things are not in the order you expect them to be, make sure the order of the block array you send is correct. Modifying the $block->weight attribute will do nothing because the block module only uses the sort on the database call to load them from the table.

To fix, run it through a sort function that looks at objects. Functions like drupal_sort_weight and element_sort will not work because they are expecting arrays, not objects. Use something like this:

function drupal_sort_weight_object($a, $b) {
  $a_weight = (is_object($a) && isset($a->weight)) ? $a->weight : 0;
  $b_weight = (is_object($b) && isset($b->weight)) ? $b->weight : 0;
  if ($a_weight == $b_weight) {
    return 0;
  return ($a_weight < $b_weight) ? -1 : 1;

And then at the bottom of your function:

uasort($blocks, "drupal_sort_weight_object");

This will make sure any modifications to weight are properly applied.