26

I've created a block using hook_block_info and hook_block_theme and the like. But how can I theme it?

I have it working to return an array with the keys 'subject' and 'content'. But I created the markup directly in the hook_block_view() hook and that's not what I want.

In the docs it's said that content should preferably returned as renderable array and not as markup. But what is this renderable array? They say it should be data instead of markup, but all I see in the examples is that it's just used as a wrapper for markup, so nothing gained there.

I want to be able to have a block--MYMODULE--DELTA.tpl.php in my theme but how do I call it and how can I pass the data to the block?

2
  • detail blog: goo.gl/kD3TZu Commented Jul 14, 2015 at 13:18
  • @SureshKamrushi – OP asks for theming a block. The linked article is about adding a new region to a theme. Which is not what OP asked for.
    – leymannx
    Commented Jan 3, 2019 at 11:31

4 Answers 4

28

The way I do this is as follows...

function MYMODULE_block_info() {

  $blocks = [];

  $blocks['my_block_machine_name'] = [
    'info'  => t('My Block Title'),
    // @see https://api.drupal.org/api/drupal/includes!common.inc/group/block_caching/7.x
    // You can use different caching options.
    'cache' => DRUPAL_NO_CACHE,
  ];

  return $blocks;
}

function MYMODULE_block_view($delta = '') {

  $block = [];

  switch ($delta) {
    case 'my_block_machine_name':
      // Good idea to check user permissions here.
      if (user_access('access content')) {
        $block['subject'] = t('My Block Title');
        $block['content'] = MY_BLOCK_CONTENT_CALLBACK();
      }
      break;
  }

  return $block;
}

function MY_BLOCK_CONTENT_CALLBACK()() {

  $items = [];

  // This is the simplest kind of renderable array.
  $items['VAR_ONE'] = ['#markup' => 'VAR_ONE_OUTPUT'];

  // Here I added a prefix and a suffix.
  $items['VAR_TWO'] = [
    '#prefix' => '<div class="foo-bar">',
    '#markup' => 'VAR_TWO_OUTPUT',
    '#suffix' => '</div>',
  ];

  // This is where the $items get sent to your my-template.tpl.php template
  // that got registered below.
  return theme('my_cool_block', ['items' => $items]);
}

function MYMODULE_theme() {

  // Here you are registering your template for the block output above.
  $module_path = drupal_get_path('module', 'MYMODULE');

  // Drupal will now look up your modules /theme folder first to grab the
  // template.
  $base = [
    'path' => "$module_path/theme",
  ];

  return [
    'my_cool_block' => $base + [
        // Leave off .tpl.php.
        'template'  => 'my-template',
        // Define variables you want to pass to the template.
        // Here I just pass items, but you can pass any other data as well.
        'variables' => [
          'items' => NULL,
        ],
      ],
  ];
}

And then in a subfolder in your module called theme there should be a file called my-template.tpl.php which could have this in it:

<?php 

$items = $variables['items'];

print render($items['VAR_ONE']); 
print render($items['VAR_TWO']); 

And if you wanted to, you could actually overwrite the "default" module implementation you just made for my-module.tpl.php in your theme as you wish in block--MYMODULE--DELTA.tpl.php.

2
  • But if I overule the theme with a tpl.php file in my theme, the hook_block_view won't execute and my variables are not given to the temmplate file.
    – yunzen
    Commented Mar 19, 2013 at 15:41
  • @yunzen - You might need to empty you cache, try going to admin/config/development/performance and click the clear cache button. You can also clear the cache using drush i.e drush cc all Commented Mar 17, 2017 at 15:40
6

Try Theme Developer module. When you have enabled it you can check a checkbox in bottom left corner of you Drupal page. After that you can click on your block and get useful information considering theming. You can see the possible .tpl.php file namings for your block for example.

Pick one of those names. The first is the most specific one. It will only theme one block. Create a file with that name in your theme folder if it's not already there. You can put it in subfolder if you want to get organized.

Copy the content of block.tpl.php in your file and start changing things to the way you want them to be.

Save your file, clear caches and reload the page.

0
5

There's already a number of answers for this question but I have tried to provide a very simplistic approach. Hopefully identifying to devs the array structure expected by Drupal when returning your block content.

To do this I have broken the question down into separate code examples as such,

/**
 * Implements hook_theme().
 */
function examplemodule_theme() {
  return array(
    'examplemodule_output' => array(
      'variables' => array(
        'title' => NULL,
        'content' => NULL,
        'popular_content' => NULL,
       ),
      'template' => 'templates/examplemodule-sweet--block',
    ),
  );
}

Please see a full explanation here drupal 7 creating theming custom blocks

3

This is an old post, but I have found a better solution for overriding block templates from a custom module for Drupal 7.

Add this to your custom module:

/**
 * Implements hook_theme().
 */
function MYMODULE_theme($existing, $type, $theme, $path) {

  // Custom template for that overrides the default block.tpl.php.
  $themes['block__my_custom_module'] = [
    'template'      => 'block--my_custom_module',
    'original hook' => 'block',
    'path'          => drupal_get_path('module', 'my_custom_module') . '/templates',
  ];

  return $themes;
}

Then you need the follow code:

/**
 * Implements hook_block_info().
 */
function MYMODULE_block_info() {

  $blocks = [];

  $blocks['my_custom_module'] = [
    'info'  => t('My Custom Module Block'),
    'cache' => DRUPAL_CACHE_PER_ROLE,
  ];

  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function MYMODULE_block_view($delta = '') {

  $block = [];

  switch ($delta) {
    case 'my_custom_module':
      $block['content'] = _my_custom_module_helper_function();
      break;
  }

  return $block;
}

/**
 * Helper function to generate HTML.
 *
 * @return string
 *   generated HTML
 */
function _my_custom_module_helper_function() {

  $output = '';

  // ...

  return $output;
}

All you have to do is create templates/block--my-custom-module.tpl.php inside your module's folder.

I have written a tutorial about this Drupal Tutorial - How to Override a Block Templates from a Custom Module

0

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.