14

I'm using Drupal 7. Right now, I have a main-menu navigation and Language switcher that exists in my website header. I placed them there by going to the CMS>Structure>Blocks and hten dragging the blocks into the header region.

How do I programmatically situate these block in the header?

2
  • According your question about how to programmatically situate these block in the header, I suggest review Examples module http://drupal.org/project/examples and specifically you can review and enable the module Block Example to test working your block in a programatically way. I guess that block_example_block_info() and 'region' value could be useful to test.
    – cigotete
    Aug 20, 2011 at 4:23
  • John, have you come up with an answer to this?
    – relipse
    Jan 14, 2016 at 17:26

7 Answers 7

4

To alter the region where blocks defined by other modules are placed, you can implement hook_block_info_alter(), which receives the following arguments:

  • $blocks (passed by reference): the array containing the block definitions, keyed by module, and delta
  • $theme: the theme for which the blocks are being defined
  • $code_blocks: the blocks as defined from the hook_block_info() implementations, before their values are overridden by the values obtained from the database
3

It is legitimate to add a renderable array to any page region in hook_page_build(). Drupal 7 example to add a minipanel to the footer region.

<?php
/**
 * Implements hook_page_build().
 */
function MODULE_page_build(&$page) {
  $block = module_invoke('panels_mini', 'block_view', 'blah');
  $blocks['blah'] = array('#markup' => $block['content']);

  $region = 'footer';
  if (isset($page[$region])) {
    $page[$region] = array_merge($page[$region], $blocks);
  }
  else {
    $page[$region] = $blocks;
  }
}

This is the very same technique that uses context module.

Note: you don't need block.module enable for this to work.

2

In D6 it would essentially be

$block = module_invoke("the_module_name", "block", "view", the_block_delta);
drupal_set_content("the_region_name", theme("block", $block));

In D7 I think it is

$block = module_invoke("the_module_name", "block_view", the_block_delta);
drupal_add_region_content("the_region_name", theme("block", $block));

but I am still getting up to speed on D7.

2
  • This doesn't allow to third-party modules to alter the block being output, as modules could implement hook_block_view_alter that is not invoked with the code you shown.
    – apaderno
    Aug 21, 2011 at 13:26
  • Believe drupal_add_region_content() is a dead end as it's intended for install / upgrade pages.
    – doublejosh
    May 29, 2012 at 18:01
2

If you are adding a custom block you do this using hook_block_info, setting the status option to 1 and the region option to the region you want the block to be placed into.

Example:

MODULE_block_info() {
  $blocks = array();
  $blocks['my_block'] = array(
    'info' => t('My Block Name'),
    'status' => 1,
    'region' => 'THE_REGION_I_WANT',
   );
   return $blocks;
}

If you are wanting to change an already existing block, you would use hook_block_info_alter() instead, updating the same options has shown below.

Example:

MODULE_hook_block_info_alter(&$blocks, $theme, $code_blocks) {
  $blocks['my_block']['status'] = 1;
  $blocks['my_block']['region'] = 'THE_REGION_I_WANT';
}

For more information see https://api.drupal.org/api/drupal/modules%21block%21block.api.php/function/hook_block_info/7

0

This code is based on @jonhattan's, but his doesn't render the block container HTML or contextual links. I also provided a simple way to specify all blocks and regions in one place.

<?php
/**
 * Implements hook_page_build().
 */
function MODULE_page_build(&$page) {
  global $theme;

  // A list of blocks you wish to display, keyed by region.
  // These are in the format of: 'module_name' => 'delta'.
  $blocks_to_render = array(
    'header' => array(
      'block' => 1,
    ),
  );

  // Add the blocks to each region.
  foreach ($blocks_to_render as $region => $block_list) {
    $block_objects = array();
    foreach ($block_list as $module_name => $delta) {
      $block = block_load($module_name, $delta);
      // Alter some of the defaults to match the current context.
      $block->theme = $theme;
      $block->region = $region;
      $block->weight = 0;
      $block_objects[] = $block;
    }
    $blocks_build = _block_get_renderable_array(_block_render_blocks($block_objects));

    if (isset($page[$region])) {
      $page[$region] = array_merge($page[$region], $blocks_build);
    }
    else {
      $page[$region] = $blocks_build;
    }
  }
}

Note: Unlike his code, you DO need the block.module installed.

-1

This isn't the best form, but you can manually place content into the page array like this...

function mymodule_page_alter(&$page) {
  $my_content = _mymodule_render_mycontent();
  $page['my_region']['my_special_insert']['content']['#markup'] = $my_content;
}

Though you should stick to using Context or just core blocks. Making new plugins isn't as bad as it seems. Just name files correctly, setup a trigger and a test. example.

1
  • In fact, on second thought I almost regret posting this solution. Don't do this.
    – doublejosh
    Mar 10, 2015 at 21:54
-1

you also can adjust blocks in your theme like:

/**
 * Implements hook_preprocess_page().
 */
function your_theme_preprocess_page(&$variables) {

  if (drupal_is_front_page()) {
    $variables['page']['region_one'] = $variables['page']['region_two'];
    unset($variables['page']['region_two']);
  }
}
1
  • This does not answer the question of how to render blocks or how to identify them in the markup.
    – Christian
    Aug 20, 2015 at 2:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.