Making a custom block in Drupal, something other than a block with a title and body which is already core functionality, is something that we often end up doing when integrating services from other locations to control the display of some data. Although it may not be as elegant as integrating with a custom entity, it is far less time consuming overall and where we attempt to deliver value before perfection it fits with most customer requirements. So here we go.

Firstly, let me prepend this post by stating that this is for demonstration purposes, unless you are very keen on making a module for a specific purpose, that has a block for a specific purpose, you should probably use the Bean module which allows the field-ing (not sure that is a word) of blocks in Drupal. Certainly check it out if you feel that classic Drupal blocks don’t quite fit with what you want them to do.

When making a custom module, you will require all of the normal things when making a module. A .info file and a .module file. We will be working exclusively on a .module file but you can look up (https://www.drupal.org/node/542202)[what should be in a Drupal .info file].

1. Create the block

Firstly we must inform Drupal that the block exists. This is done by using hook_block_info() and giving the block a unique name. You can look for finding out more about using (https://api.drupal.org/api/drupal/modules%21block%21block.api.php/function/hook_block_info/7)[hook_block_info()].

/**
 * Implements hook_block_info().
 */
function MYMODULE_block_info() {
  $blocks = array();
  $blocks['my_new_block'] = array(
    'info' => t('My New Block'),
  );
  return $blocks;
}

This will create a block for you in the structure > blocks admin screen.

2. Create Block View

Creating a block view means that you can configure the display of the block and what appears in its regions (title and content). You can find out more about using (https://api.drupal.org/api/drupal/modules%21block%21block.api.php/function/hook_block_view/7)[hook_block_view()].

/**
 * Implements hook_block_view().
 */
function MYMODULE_block_view($delta = '') {
  $block = array();
  switch ($delta) {
    case 'my_new_block':
      $block['title'] = 'My New Block';
      $block['content'] = t('Hello World');
      break;
  }
  return $block;
}

3. Configure the Block

This will then work fine as a custom block. However if you want to extend it you will need to look at configuring the block and adding fields. We are just going to save the variables using variable_set() which will work find for most purposes. We create both the field and get a default value from when we save the block, which is step 4. You can of course find out more about using (https://api.drupal.org/api/drupal/modules%21block%21block.api.php/function/hook_block_configure/7)[hook_block_configure()].

/**
 * Implements hook_block_configure().
 */
function MYMODULE_block_configure($delta = '') {
  $form = array();
  switch ($delta) {
    case 'my_new_block':
      $form['my_variable'] = array(
        '#type' => 'textfield',
        '#title' => t('Cart ID'),
        '#size' => 10,
        '#default_value' => variable_get('my_variable'),
      );
      break;
  }
  return $form;
}

4. Saving the Block

After you have created fields inside your block, you will need to save them otherwise they will not be kept with the block. We are simply saving to the variables table in the database. You can, or course, find out more about (https://api.drupal.org/api/drupal/modules%21block%21block.api.php/function/hook_block_save/7)[hook_block_save()].

/**
 * Implements hook_block_save().
 */
function MYMODULE_block_save($delta = '', $edit = array()) {
  switch ($delta) {
    case 'my_custom_block':
      variable_set('my_variable', $edit['my_variable']);
      break;
  }
}

You now have a new block with custom fields. Well done! Obviously there are numerous ways that you can look at extending this, but this should serve as a useful method for doing it. I have attached MYMODULE.module as a file, which you can download or copy and past the whole thing below.

/**
 * Implements hook_block_info().
 */
function MYMODULE_block_info() {
  $blocks = array();
  $blocks['my_new_block'] = array(
    'info' => t('My New Block'),
  );
  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function MYMODULE_block_view($delta = '') {
  $block = array();
  switch ($delta) {
    case 'my_new_block':
      $block['title'] = 'My New Block';
      $block['content'] = t('Hello World');
      break;
  }
  return $block;
}

/**
 * Implements hook_block_configure().
 */
function MYMODULE_block_configure($delta = '') {
  $form = array();
  switch ($delta) {
    case 'my_new_block':
      $form['my_variable'] = array(
        '#type' => 'textfield',
        '#title' => t('Cart ID'),
        '#size' => 10,
        '#default_value' => variable_get('my_variable'),
      );
      break;
  }
  return $form;
}

/**
 * Implements hook_block_save().
 */
function MYMODULE_block_save($delta = '', $edit = array()) {
  switch ($delta) {
    case 'my_custom_block':
      variable_set('my_variable', $edit['my_variable']);
      break;
  }
}