Hi all,

I'm currently coding a Drupal module - actually I'm revising a pre-existing one. Essentially, it's a block module that displays information in the sidebar, based on information the module gets from an external API.

I'm quite new to module development, in fact this is only my second module ever. So, I'm not entirely sure how to return an HTML markup to be displayed in the sidebar - for example:

<h2>Title</h2>
<img class="module-name-center-image" src="image/source.src">
<h3>Caption</h3>

At the moment, I'm simply having my 'module_name_block_contents' function returning that raw markup. As in:

return "<h2>Title</h2>
        <img class="module-name-center-image" src="image/source.src">
        <h3>Caption</h3>"

Which I'm told is NOT the best practice. So, how would I do it?

Thanks in advance!

Comments

nevets’s picture

What you show is confusing in the context of the Drupal API.

My assumption is your module implements hook_block_view()

It returns an array of elements, 'subject' which is the block title, and 'content' which is a rendable array of what to display.

So given your code the return from hook_block_view() might look like

$block = array(
  'subject' => 'Title',
  'content' => array(
        '#theme' => 'image',
        '#path' => 'image/source.src',
        '#attributes' => array('class' => 'module-name-center-image'),
   )
);

return $block;
Peregrine2976’s picture

Hey - yes, by 'module_name_block_view()' I meant 'hook_block_view()', since 'hook' is replaced by your module name.

So how would I add another piece of content? The piece of example code you've shown would only return a single image if I understand it, but my block view needs to show several images and header elements. Additionally, is there any documentation on this? I've been unable to find anything remotely useful.

nevets’s picture

Look at the first comment in hook_block_view(), it takes you to a discussion on render arrays.

jaypan’s picture

Let's imagine your external web service returns the following array:

$values = array('name' => 'Peregrine', 'species' => 'bird', 'type' => 'falcon');

You can create the block for this as follows:

function mymodule_block_view($delta = '')
{
  if($delta == 'myblock')
  {
    $values = get_values_from_webservice(); // Returns the array above
    $block = array
    (
      'subject' => t('My Block'),
      'content' => array
      (
        // I always add an arbitrary layer, keyed DELTA_block
        'myblock_block' => array
        (
          '#theme' => 'mymodule_myblock_block', // MODULE_DELTA_block
          '#values' => $values,
        ),
      ),
    );
    return $block;
  }
}

There are a few points with the above code:

1) I put block contents in an array with the key DELTA_block. This is for two reasons. The first is when you are running hook_page_alter or other code that shows the entire page in a render array, this helps easily identify what the block is. The other reason is that if you add a #prefix and #suffix to blocks, and you don't have this key, the prefix and suffix wrap the entire block, which can result in invalid HTML if you use <p/> tags. If you put your #prefix and #suffix inside this array, they will wrap the block contents only.

2) The array is given the theme mymodule_block_block which is MODULE_DELTA_block. This is arbitrary, but works as a good naming convention. We need to register this theme below, and create the theme function.

Next, register the theme function:

function mymodule_theme()
{
  return array
  (
    'mymodule_myblock_block' => array
    (
      'variables' => array('values' => array()),
    ),
  );
}

Finally, we will create our theme function, which is uses the theme key we registered above, prefixed with theme_. We will build our HTML in here:

function theme_mymodule_myblock_block($variables)
{
  $values = $variables['values'];
  $output = '<h2>' . $values['name'] . '</h2>';
  $output .= '<p>' . t('Species: @species', array('@species' => $values['species'])) . '</p>';
  $output .= '<p>' . t('Type: @type', array('@type' => $values['type'])) . '</p>';

  return $output;
}

You can add/remove/alter the HTML all you want in the theme function, and it can also be overridden in the site theme itself.

Contact me to contract me for D7 -> D10/11 migrations.