7.x block.api.php hook_block_view($delta = '')

Return a rendered or renderable view of a block.


$delta: Which block to render. This is a unique identifier for the block within the module, defined in hook_block_info().

Return value

Either an empty array so the block will not be shown or an array containing the following elements:

  • subject: The default localized title of the block. If the block does not have a default title, this should be set to NULL.
  • content: The content of the block's body. This may be a renderable array (preferable) or a string containing rendered HTML content. If the content is empty the block will not be shown.

For a detailed usage example, see block_example.module.

See also




Related topics

17 functions implement hook_block_view()

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

aggregator_block_view in modules/aggregator/aggregator.module
Implements hook_block_view().
block_block_view in modules/block/block.module
Implements hook_block_view().
block_test_block_view in modules/block/tests/block_test.module
Implements hook_block_view().
blog_block_view in modules/blog/blog.module
Implements hook_block_view().
book_block_view in modules/book/book.module
Implements hook_block_view().

... See full list


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


function hook_block_view($delta = '') {

  // This example is adapted from node.module.
  $block = array();
  switch ($delta) {
    case 'syndicate':
      $block['subject'] = t('Syndicate');
      $block['content'] = array(
        '#theme' => 'feed_icon',
        '#url' => 'rss.xml',
        '#title' => t('Syndicate'),
    case 'recent':
      if (user_access('access content')) {
        $block['subject'] = t('Recent content');
        if ($nodes = node_get_recent(variable_get('node_recent_block_count', 10))) {
          $block['content'] = array(
            '#theme' => 'node_recent_block',
            '#nodes' => $nodes,
        else {
          $block['content'] = t('No content available.');
  return $block;


kenyangzj’s picture

For those who don't know what a Renderable Array is, here's the explanation: http://randyfay.com/node/79

chrisroane’s picture

If you call drupal_add_js() inside a block and have caching enabled for that block, that JS code will not be included after the block gets cached!

It took me a bit of time to figure this out. There is a way to include the JS you need and still enable caching for the html. To do this, following these instructions.

#1: Turn off full caching for the block under hook_block_info() by setting 'cache' to: DRUPAL_NO_CACHE

#2: In hook_block_view() cache the output of the html after adding the JS. Below is a sample function that I call that does this and returns the cached block after it has been generated. In this example, I'm making a cached block per user, but that isn't required.

 * The dashboard tabs block.
function _tbf_dashboard_tabs_block() {
  global $user;
  // Add the JS to make the tabs work.
  drupal_add_library('system', 'ui.tabs');  
  drupal_add_js('jQuery(function() { jQuery("#tabs").tabs(); });', 'inline');
  $cache_name = 'dashboard_tabs_' . $user->uid;
  $cache = cache_get($cache_name, 'cache_block');
  // Is the tab html cached already?
  if (!empty($cache) && isset($cache->data) && !empty($cache->data)) {
    // It is cached. Return the cached content.
    return $cache->data;
  else {
    // Grab the html from the tabs template file.
    $tab_html = theme('dashboard_tabs');
    // Cache for 24 hours.
    cache_set($cache_name, $tab_html, 'cache_block', time() + 86400);
    return $tab_html;
chrisroane’s picture

Like "4elove4ekFs" pointed out, to have JS/CSS be attached to a block when caching is on, you should use the #attached property.

Here is the code in how to do this:

$block['content'] = array(
  '#markup' => mymodule_testblock_content(),
  '#attached' => array(
      'css' => array(
        drupal_get_path('module', 'mymodule') . '/css/mymodule.css',
      'js' => array(
        drupal_get_path('module', 'mymodule') . '/js/mymodule.js',
kingandy’s picture

Technically if you're using your own caching you should set the block's 'cache' property to DRUPAL_CACHE_CUSTOM rather than DRUPAL_NO_CACHE, but I don't know if this has any actual impact beyond information for other developers. (#attached is still ideal for this purpose, though.)

NikaDevs’s picture

Just use rendered array and '#attached' property

iMiksu’s picture

If you run into an PHP fatal error:

PHP Fatal error: Unsupported operand types in .../modules/block/block.module on line 352

...while trying to access "admin/dashboard" path, it may be caused by your block view using string type as content instead of renderable array.

iamEAP’s picture

I often get confused about how to hide a block's title in code. Probably because, through the UI, you type "<none>" but you do not do so in code. Here's a breakdown of what's acceptable:

function hook_block_view($delta = '') {
  // All of these are functionally identical.
  $block['subject'] = '';
  $block['subject'] = NULL; // Or just don't set.
  $block['title'] = '<none>'; // Undocumented, but works.
  // This will not behave as desired.
  $block['subject'] = '<none>';
MKorostoff’s picture

In Drupal 8 this is deprecated, and replaced with the "Block API" more information here https://api.drupal.org/api/drupal/core%21modules%21block%21block.api.php...

SKAUGHT’s picture

this thread is still d7 api

kingandy’s picture

Yeah, it's useful for API docs to have forward links so people used to using the D7 hooks can quickly find how to upgrade their code.

vbouchet’s picture

Is there any reason to not have a specific hook_block_view for each block (as it exists for the hook_block_view_alter())?
It would save us from this huge list of switch/case or else/if in hook_block_view() implementation.
It may also be useful to have a "view callback" and/or "view callback file" in hook_block_info() so we can do the entire block view process outside the module file.

doublejosh’s picture

Be aware that hook_block_view() will only be called for the module instantiating the block. Therefor it's unnecessary to include the name of the module in the delta... and it's not the right place to make changes to blocks in general. This differs from hooks like hook_entity_view().

webdevfreak’s picture

We have a module 'event_management' and this code will create a block programmatically which infact displays 3 most recent records from node entity.

Here is the link to the complete module: https://bitbucket.org/webdevfreak/event-management/src

 * Implements hook_block_info().
function event_management_block_info() {
  $blocks['upcoming_events'] = array(
    'info' => t('Upcoming Events'),

  return $blocks;

 * Implements hook_block_view().
function event_management_block_view($delta = '') {
  switch ($delta) {
    case 'upcoming_events':

      // Block title.
      $block['subject'] = '

' . t('Upcoming Events') . '

'; // Query node entity and fetch result. $query = new EntityFieldQuery(); $entities = $query->entityCondition('entity_type', 'node') ->entityCondition('bundle', 'event') ->propertyOrderBy('created', 'DESC') ->range(0, 3) ->execute(); // Initialise array value as empty. $block['content'] = ''; // Loop through entity quesry result and build a result string. foreach ($entities['node'] as $obj) { $node = node_load($obj->nid); $block['content'] .= l($node->title, "node/" . $node->nid) . '
' . date('d-m-Y', strtotime($node->field_event_date['und'][0]['value'])) . '

'; } break; } // Return result string to render on the block. return $block; }