function hook_block_info

You are here

7 block.api.php hook_block_info()

Define all blocks provided by the module.

This hook declares to Drupal what blocks are provided by your module and can optionally specify initial block configuration settings.

In hook_block_info(), each block your module provides is given a unique identifier referred to as "delta" (the array key in the return value). Delta values only need to be unique within your module, and they are used in the following ways:

  • Passed into the other block hooks in your module as an argument to identify the block being configured or viewed.
  • Used to construct the default HTML ID of "block-MODULE-DELTA" applied to each block when it is rendered. This ID may then be used for CSS styling or JavaScript programming.
  • Used to define a theming template suggestion of block__MODULE__DELTA, for advanced theming possibilities.
  • Used by other modules to identify your block in hook_block_info_alter() and other alter hooks.

The values of delta can be strings or numbers, but because of the uses above it is preferable to use descriptive strings whenever possible, and only use a numeric identifier if you have to (for instance if your module allows users to create several similar blocks that you identify within your module code with numeric IDs). The maximum length for delta values is 32 bytes.

Return value

An associative array whose keys define the delta for each block and whose values contain the block descriptions. Each block description is itself an associative array, with the following key-value pairs:

  • info: (required) The human-readable administrative name of the block. This is used to identify the block on administration screens, and is not displayed to non-administrative users.
  • cache: (optional) A bitmask describing what kind of caching is appropriate for the block. Drupal provides the following bitmask constants for defining cache granularity:

  • properties: (optional) Array of additional metadata to add to the block. Common properties include:

    • administrative: Boolean that categorizes this block as usable in an administrative context. This might include blocks that help an administrator approve/deny comments, or view recently created user accounts.
  • weight: (optional) Initial value for the ordering weight of this block. Most modules do not provide an initial value, and any value provided can be modified by a user on the block configuration screen.
  • status: (optional) Initial value for block enabled status. (1 = enabled, 0 = disabled). Most modules do not provide an initial value, and any value provided can be modified by a user on the block configuration screen.
  • region: (optional) Initial value for theme region within which this block is set. Most modules do not provide an initial value, and any value provided can be modified by a user on the block configuration screen. Note: If you set a region that isn't available in the currently enabled theme, the block will be disabled.
  • visibility: (optional) Initial value for the visibility flag, which tells how to interpret the 'pages' value. Possible values are:

    Most modules do not provide an initial value for 'visibility' or 'pages', and any value provided can be modified by a user on the block configuration screen.

  • pages: (optional) See 'visibility' above. A string that contains one or more page paths separated by "\n", "\r", or "\r\n" when 'visibility' is set to BLOCK_VISIBILITY_NOTLISTED or BLOCK_VISIBILITY_LISTED (example: "<front>\nnode/1"), or custom PHP code when 'visibility' is set to BLOCK_VISIBILITY_PHP. Paths may use '*' as a wildcard (matching any number of characters); '<front>' designates the site's front page. For BLOCK_VISIBILITY_PHP, the PHP code's return value should be TRUE if the block is to be made visible or FALSE if the block should not be visible.

For a detailed usage example, see block_example.module.

See also

hook_block_configure()

hook_block_save()

hook_block_view()

hook_block_info_alter()

Related topics

17 functions implement hook_block_info()

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

aggregator_block_info in modules/aggregator/aggregator.module
Implements hook_block_info().
block_block_info in modules/block/block.module
Implements hook_block_info().
block_test_block_info in modules/block/tests/block_test.module
Implements hook_block_info().
blog_block_info in modules/blog/blog.module
Implements hook_block_info().
book_block_info in modules/book/book.module
Implements hook_block_info().

... See full list

4 invocations of hook_block_info()
block_admin_configure in modules/block/block.admin.inc
Form constructor for the block configuration form.
block_form_user_profile_form_alter in modules/block/block.module
Implements hook_form_FORM_ID_alter() for user_profile_form().
dashboard_page_build in modules/dashboard/dashboard.module
Implements hook_page_build().
_block_rehash in modules/block/block.module
Updates the 'block' DB table with the blocks currently exported by modules.

File

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

Code

function hook_block_info() {
  // This example comes from node.module.
  $blocks['syndicate'] = array(
    'info' => t('Syndicate'),
    'cache' => DRUPAL_NO_CACHE,
  );

  $blocks['recent'] = array(
    'info' => t('Recent content'),
    // DRUPAL_CACHE_PER_ROLE will be assumed.
  );

  return $blocks;
}

Comments

In my experience, the following will break the jQuery object, throwing "jQuery is not defined":

< ? php
drupal_add_js(drupal_get_path('module', 'mymodule') . '/js/mymodule.js');

It must be used within a function. The following will work :

< ? php
function mymodule_block_view($delta=''){
drupal_add_js(drupal_get_path('module', 'eyedsafe') . '/js/eyedsafe.js');

Since this is different than D6, I wanted to point it out.

This is still the wrong way to add JS to a block. See documentation on render arrays and the #attached property.

I have a difficult time with certain developers preaching about the right and wrong way to do something in Drupal. For many features, there are many ways of accomplishing them. In this case, using #attached in a hook requires access to the $page or &$page reference such as in hook_page_alter in a module. But then you have to filter the call with conditional logic based on your block's visibility (which the block or context is already doing if you use a block API function). You can also put calls to drupal_add_js() in a theme template function such as preprocess_page() but again, you either get it on every page or you have to add logic to check the block conditions.

If loading certain js that is only going to be used on a specific block works fine in hook_block_view, you have the advantage of this function only getting called for the block that needs the js with the delta parameter as the only qualifier needed to know what code to run for this specific block. If your block has conditions or a context with conditions, the hook_block_view should not even get called for your block if the conditions are not met by the logged in user or page url. It seems like a perfectly sound way of encapsulating the js that is specific only to your block when you know it does not need to be loaded anywhere else.

If there's a possibility you're going to need the js in other blocks or pages, the simplest place to put them (and any related css) is in the theme .info file.

I stand corrected. After further research, I believe what dalin was referring to was building the block array in hook_block_view as shown in the example on https://api.drupal.org/api/drupal/modules!block!block.api.php/function/h...

with the switch statement using the $delta parameter along with the example of creating the $content array as an #attached render array described in the comment by chrisroane https://api.drupal.org/comment/44413#comment-44413 which looked like 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',
    ),
  ),
);

Using this technique, you can encapsulate the js and css loading in your module_block_view and not have to place it in a hook_page_alter or theme preprocess_page() hook. Hope that clarifies things a little better.

I stand corrected. After further research, I believe what dalin was referring to was building the block array in hook_block_view as shown in the example on https://api.drupal.org/api/drupal/modules!block!block.api.php/function/h...

with the switch statement using the $delta parameter along with the example of creating the $content array as an #attached render array described in the comment by chrisroane https://api.drupal.org/comment/44413#comment-44413 which looked like 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',
    ),
  ),
);

Using this technique, you can encapsulate the js and css loading in your module_block_view and not have to place it in a hook_page_alter or theme preprocess_page() hook. Hope that clarifies things a little better.

I was unable to find how to set the content-types for which this block should be visible, and found out that it is actually handled in the node module. So I finally did this:

<?php
function hook_block_info() {
    ...
   
// Limit on node types
   
$form_state = array(
       
'values' => array(
           
'module' => '...',
           
'delta'  => '...',
           
'types'  => array('...', '...'),
        ),
    );
   
node_form_block_admin_configure_submit(NULL, $form_state);
    ...
}
?>

Not sure if it is actually a preferred way, but at least it works in a way so that the settings can still be changed through the admin interface.

Drupal doesn't seem to expose a means of filtering by content type on the hook_block_info, or really anywhere but the UI.

However, examine the contents of the table block_node_type. It has the module name, block delta/name, and then the content type it's filtered too. You can edit this directly to filter it.

This is probably a bad idea, but it'll work.

This code shows an example of a block containing a link that only appears when the user hasn't already logged in.

<?php
// ...
function loginlink_block_info() {
 
$blocks['myloginlink'] = array(
   
'info' => t('Login Link'),
   
'status' => TRUE,
   
'region' => 'sidebar_first',
   
'visibility' => BLOCK_VISIBILITY_PHP,
   
'pages' => '<?php global $user; if ($user->uid == 0) return TRUE; else return FALSE; ?>
'
  );
// ..
?>

Important: Verify that the PHP filter module is enabled if you want to use BLOCK_VISIBILITY_PHP!

Setting block region doesn't work unless you set status to 1.
Hope this saves someone some time.

Just wanted to leave a message saying Thanks.
Was driving me crazy.

And just confirming to people as well that the region name is the machine name found in the template.info file.
In my instance, 'Main Content' is called 'content'.

I have checked that by uninstalling mymodule and it works without
set status to 1.

if you use $block['block_name]['region'] you must declare $block['block_name]['status'] in TRUE in order to work, if not you will get a php warning when loads the module/site

Hi,

like mentioned above, I'd need to set the status to 1 to get region to work - anything similar needed for pages? I've set status to 1, visibility to BLOCK_VISIBILITY_LISTED and pages to 'mypath'. Cleared all caches, and my block still shows on all pages.

Can anyone help?

Thanks a lot

Uninstall the module providing the block, then re-enable the module.

It seems that once you do anything to the block via Drupal's UI, your UI config overrides the config in code. By uninstalling the module providing the block, I believe you're removing any stored settings in the DB surrounding that block. Maybe someone is aware of a "revert to default" block action from within the UI, but I haven't found it.

There's also a theme key-value pair:

'exposed_order' => array(
'info' => t('Exposed commerce order filter'),
'theme' => $admin_theme,
'region' => 'content',
'pages' => ORDER_MENU_LINK,
'status' => 1,
'visibility' => 1,
),

This is a quick and easy example:

/**
* Implements hook_block_info().
*/
function example_block_info() {
  $blocks['ad_banner1'] = array(
    'info' => t('Ad Banner 1'),
  );
  $blocks['ad_banner2'] = array(
    'info' => t('Ad Banner 2'),
  );

  return $blocks;
}

/**
* Implements hook_block_view().
*/
function example_block_view($delta = '') {
  $block = array();

  switch ($delta) {
    case 'ad_banner1':
      $block['content'] = 'shtuffenins';
      break;

    case 'ad_banner2':
      $block['content'] = 'shtuffenins2';
      break;
  }

  return $block;
}

hi
i need to create a block while the submit button clicked

I have a module that simply adds a few blocks. I enabled it and the blocks were added. I added some other blocks to it as well, but the new blocks do not appear even after I refresh cache. Then I created and enabled other modules that add blocks and none of these blocks appear. When I enable/disable the original module, the same blocks that showed up show up again but nothing I do will make any of the other blocks show up.

Here is the code.

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

  $blocks = array();

  $blocks['footer_first_block_1'] = array(
    // info: The name of the block.
    'info' => t('Footer first block 1'),
    'status' => TRUE,
    'weight' => 1,
  );
 
  $blocks['footer_first_block_2'] = array(
    'info' => t('Footer first block 2'),
    'status' => TRUE,
    'weight' => 2,
  );
 
  $blocks['footer_first_block_3'] = array(
    'info' => t('Footer first block 3'),
    'status' => TRUE,
    'weight' => 3,
  );

  $blocks['footer_first_block_4'] = array(
    'info' => t('Footer first block 4'),
    'status' => TRUE,
    'weight' => 4,
  );

  return $blocks;
}

So footer_first_block_4 is the block I added.... but it doesn't show up, nor do any other blocks I add in a similar fashion. However I enabled blocks_example and it works fine (this as a sanity check). I've refreshed cache many many times and it doesn't help. Any ideas how this can possibly happen?

I ran into the same issue as agalligani. Looked at the block table in MySQL and saw that the region column had no value for new blocks that were not showing up in the block admin page. This is odd because the region column is set to not have any NULL values. Perhaps the default value should be "-1". When I changed the regions of my missing blocks to -1, they then showed up on the admin page.