Drupal 6 Displaying a block multiple times on the same page or in different regions

By shane
Wed, 2013-03-06 10:00
10 comments

There are some times in Drupal 6 where you push the limits of what the blocks interface can do. If you need to display the same block, multiple times on the same page, you will start to see these limitations. An example of where this is useful is a Newsletter signup form. Sometimes a client may want a newsletter signup form to be in the footer of every page, but also displayed more prominently on the contact form page.

You will also run into this issue if you want to output a block in one region on one page and another region on a separate page. An example of this would be to display the newsletter signup form in the header on the front page, but in the footer on every other page of the site.

Both of these examples can easily be achieved using something like Panels or Display Suite, but if you want to stick to the blocks interface, here is a simple way you can solve this by building a custom Drupal 6 module.

The first step is to create a simple Drupal 6 module. After you have the module created, we need to create our own Drupal 6 block. Drop the following code in your .module file. You will need to replace the module name with the name of your module. You will also need to look through the other code replacing text and descriptions as necessary. In my example I will be going through creating a second block for the Drupal 6 Constant Contact module.

/**
 * Implements hook_block().
 */
function MYMODULE_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    $blocks[0] = array('info' => t('Constant Contact Block 2'));
 
    return $blocks;
  }
  else if ($op == 'view') {
    switch ($delta) {
      case 0:
        // Your module will need to define this function to render the block.
        $block = array(
          'subject' => t('Title of block #1'), 
          'content' => '',
        );
        break;
    }
    return $block;
  }
}

The next step is to identify the block you want to display. The best way to do this is to figure out which module you need to duplicate the block for. In my example this was the Constant Contact module. Open up the .module file for whichever module you want to duplicate the block for.

Once you have the module file opened, do a search for "_block" or "hook_block". This should get us to the function that has all the details you need to insert the line of code that will print this block. We need to get the module name and the delta value for our block. Here is an example from the constant_contact.module file's hook_block implementation.

/**
 * Enables us to place a signup form into a block
 */
function constant_contact_block($op = 'view', $delta = 0, $edit = array())
{
	switch($op) {
		case 'list':
			$blocks[0] = array(
				'info' => t('Constant Contact Signup Form'),
				'visibility'      => 0,
				'roles'      => array(1),
				'pages'      => 'user*',
			);
		return $blocks;
		case 'configure':
			$form = array();
		return;
		case 'save':
		return;
		case 'view':
			switch ($delta) {
				case 0:
					$block['subject'] = t('Signup');
					$block['content'] = drupal_get_form('constant_contact_signup_form');
				break;
			}
		return $block;
	}
}

I can pull out the module name from the function constant_contact_block and get that "constant_contact" is the module name. You can also take this from whatever is in front of the .module in the constant_contact.module file name.

The next step is to pull out the delta value for the block. This is displayed below the switch ($delta) { line of code. In this "case" we want the number "0". This is pulled from the case 0: line of code. Blocks may have multiple of these case statements, you will need to find the right delta value for the block you want to display. Many times in a Drupal 6 hook_block implementation this will simply be 0.

We now add the following line of code to our modules hook_block function.

$block = module_invoke('MYMODULE', 'block', 'view', [DELTA]);

We replace MyMODULE with the module name, in this case "constant_contact" and we replace [DELTA] with the delta value, in this case 0. Here is what the finished line of code looks like:

$block = module_invoke('constant_contact', 'block', 'view', 0);

You then need to replace this line of code with what would normally be your Drupal 6 block output code. The final version of your Drupal block code should look something like this:

/**
 * Implements hook_block().
 */
function MYMODULE_tweaks_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    $blocks[0] = array('info' => t('Constant Contact Block 2'));
 
    return $blocks;
  }
  else if ($op == 'view') {
    switch ($delta) {
      case 0:
        $block = module_invoke('constant_contact', 'block', 'view', 0);
        break;
    }
    return $block;
  }
}

You can now add this block just like you would any other block. It should be an exact duplicate of the other Drupal block.

A couple notes: This approach still has it's limitations so a better solution is using something like Panels or Display Suite. However it works well for one off simple fixes on sites that are already making heavy use of blocks. Also note that if you are displaying the same block multiple times on the same page, everything should work fine, but your CSS may not validate if the block uses the same CSS ID since it will now be in multiple places inside the HTML.

Hope that helps and let me know if you have any questions.

Need to learn more Drupal?

Premium Drupal Training Online (Horizontal)

Comments

If you want a lot of control, this is definitely the way to go. If you're like me and aren't much of a module developer, you might want to try the Multiblock module. It's currently a bit hit or miss in Drupal 7, but for D6 sites it could do just what you're looking for.

http://drupal.org/project/multiblock

That is great advice, especially if you need to do this with multiple blocks. If you are module developer, it might be easier to drop in the code above, but if you want to avoid building your own custom Drupal module, the multiblock module seems like the way to go.

Thanks Marcus!

As I'm still a newbie, I certainly don't feel ready to create a module. So I've looked at Multiblock but am nervous to use it for D7 as there is no recommended version.
Do you know anything about the likelihood of that being added soon?

I've been using Context in D6 to get my blocks to display in different regions based on the conditions - the only downside to that is displaying the block multiple times on the same page without defining different context conditions that match.

What would the benefit be of having the module code you've described above, as opposed to just building out Context conditions?

There would be no major benefits to my approach. Using context would also work in this situation. The only benefit I can see is that if it is a simple situation in which you are already using the standard blocks system it would probably easy to make this one simple module than install and configure the context module.

However this depends on how comfortable a person is with module development and how comfortable the person is with context. Either way would work, more complex situations should probably default to using the context module, panels, or display suite.

Couldn't you also just do this:

/**
 * Implements hook_block().
 */
function MYMODULE_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    $blocks[0] = array('info' => t('Constant Contact Block 2'));
    return $blocks;
  }
  else if ($op == 'view') {
    switch ($delta) {
      case 0:
      case 1:
        // Your module will need to define this function to render the block.
        $block = array(
          'subject' => t('Title of block #1'), 
          'content' => '',
        );
        break;
    }
    return $block;
  }
}

Then just put block(1) in the other spot?

Not a great approach if you have a gazillion blocks already, but certainly simple and easy to do....

:)

oops!

/**
 * Implements hook_block().
 */
function MYMODULE_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    $blocks[0] = array('info' => t('Constant Contact Block 2'));
    $blocks[1] = array('info' => t('Constant Contact Block 2a'));
    return $blocks;
  }
  else if ($op == 'view') {
    switch ($delta) {
      case 0:
      case 1:
        // Your module will need to define this function to render the block.
        $block = array(
          'subject' => t('Title of block #1'), 
          'content' => '',
        );
        break;
    }
    return $block;
  }
}

Sorry, forgot the additional declaration in the 'list' section.

creating a simple Drupal 6 module was never an easy thing for me. Thank you for this post. I really appreciate the uploader of this great post.

  • If you would like wager on the web then this free pokies have many of the ideal gambling games.

Post new comment