Skip to main content

Building your first Drupal module

3rd December, 2012

Here we take you through the absolute basics of creating a module that includes help text for users installing the module.

Preface: This blog article is intended for users of Drupal 7, but some of the processes and methods outlined here will also be applicable to developers of Drupal 6 to varying degrees.

Attempting module development for the first time can be a daunting task. We won’t be delving too deep into the internal architecture of Drupal in this blog post, so a reasonable understanding of Drupal is expected from the outset.

The end result of this short tutorial should be a custom Drupal module which creates a block that when output onto a webpage displays the current time as a UNIX timestamp.

Creating our module folder

Users familiar with Drupal’s folder structure might be tempted to put any new modules in the ‘modules’ folder that resides in the root of the Drupal install. This folder is reserved for core Drupal modules and any modules developed by the user should not be put here.

The next location a user familiar with the Drupal folder structure might be tempted to put custom module code is ‘sites/all/modules’. Although a module would function correctly in this location, again, it’s advisable not to put modules here unless certain conditions are met (e.g. If you want the module to be accessible across a series of multi-sites).

Our new module folder should actually be placed within a folder that doesn’t exist by default in a Drupal installation and that is ‘sites/default/modules’, so let’s create it!

First off, navigate to ‘sites/default’ and create the folder ‘modules’ (ensure this folder also has adequate read-write permissions on your Drupal install). Next, create a folder for our Drupal module within the newly create ‘modules’ folder.  For internal purposes we have called this folder ‘curve’. When done you should have something similar to the following:

Fig 1

Fig 1

Note: Module folders (and by extension modules themselves) should follow the ‘machine-name’ Drupal format, so lowercase letters, numbers and underscores should only be used (e.g. ‘curve’, ‘curve_block_module’, ‘curve_block_module_1’). As with PHP variables, a module name should not begin with a number.

Creating our .module and .info module files

Within the ‘curve’ folder we’ve just created, create the following two files:

  • curve.info
  • curve.module

Although it’s not a technical requirement for ‘curve.module’ to exist us to be able to write any hook code, or PHP code later on we’ll need it, so let’s create it now.

Note: These two files need to have the same name as the folder we created in the previous section.

Fig 2

Fig 2

Building up our module and info files

curve.info is the file that contains all descriptive information about the module. The following are examples of data that can be stored within this file: name, description, package, files, core and dependencies.

Open ‘curve.info’ in your favourite text editor of choice and add the following:

;$Id$
name = Curve
description = This is the Curve block module.
package = Curve block module
core = 7.x
files[] = curve.module

Let’s look at what the elements actually mean / do:

  1. ;$Id$: is a placeholder for Drupal to embed version control information about the file. This should be added to the info file, but not edited beyond this.
  2. Name: This is the human-readable name of the module. Unlike the machine-readable name, this can contain spaces.
  3. Description: This is the description that appears on the module overview page (see fig 3).
  4. Package: If you want the module to appear in a specific package (packages being groups of modules on the module overview page) you would specify this here.
  5. Core: This outlines the version of Drupal that the module is intended for. If someone tries to install this on a version of Drupal other than version 7 they will get an error.
  6. Files[]: This is an associative array of all files within the module that contain PHP code. The reason they’re listed here to make Drupal aware of the fact that they’re items that need to be inspected when executing code from the module.

Additional information can be added to the *.info file (and some of the items from above can even be omitted completely). We won’t go into any of the additional facets of the info file here to try and keep this tutorial as simple as possible, but will extend upon this further in future tutorials.

Save ‘curve.info’ and navigate to http://site.com/admin/modules and you’ll notice our module now appears in the list:

Fig 3

Fig 3

Admittedly, if we were to switch our module on it at this stage it doesn’t actually do anything, so next we’re going to add code to the ‘curve.module’ file that will allow our module to interact with various ‘hooks’ and begin to get an understanding about the Drupal API.

curve.module is the file that will contain all hooks and php code written in this brief tutorial. Hooks within drupal are essentially pre-written functions that follow a specific naming convention. The three ‘hooks’ we will look at today are ‘hook_help’, ‘hook_block_info’ and ‘hook_block_view’. As you’ll have no doubt noticed they all begin ‘hook_’ . Modules installed on a Drupal site are limited to one instance of a hook and and in any hook used the initial ‘hook_’ must be replaced with the name of the module (so in our example ‘hook_help’ would become ‘curve_help’).

Following convention, all references to Drupal hooks have a comment above them showing what’s being implemented (and for more complex implementations these comments do tend to contain more detailed information).

Let’s add an instance ‘hook_help’ to our module.

/**
* Implement hook_help()
*/
function curve_help( $path, $arg ) {
    switch ($path) {
        case 'admin/help#curve':
        $output = t('Here lies help for the Curve module');
        return $output;
    }
}

In the code above, you’ll see that as mentioned above we’ve replaced ‘hook_help’ with ‘curve_help’. Immediately following this we have a switch statement that checks the path being requested by the hook. If it finds that the requested path is http://site.com/help#curve (or alternatively: http://site.com/help/curve) you’ll notice that (with the module switched on of course) you now have help documentation as shown below:

Fig 4

Fig 4

Note: We have used the translation function in the help text above, this won’t be touched upon here, but more information can be found at: http://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/t/7

If you don’t see a reference to Curve within the help section of the Drupal install it’s worth clearing the cache as this often resolves similar issues.

Next we’re going to add hook_block code to our module in the form of ‘hook_block_info’ and ‘hook_block_view’.

Immediately below ‘curve_help()’ add the following:

 
/**
* Implements hook_block_info().
*/
function curve_block_info() {
    $blocks = array();
    $blocks['curve_block'] = array(
        'info' => t('Block: Curve block'),
        'cache' => DRUPAL_NO_CACHE,
    );
    return $blocks;
}

hook_block_info() is used to define blocks. As mentioned earlier, we’re limited to one call of ‘hook_block_info()’ per module, but due to the way Drupal handles associative arrays, we can add information about several blocks in here if we need to. As discussed above, ‘hook_block_info’ in this instance is replaced with ‘curve_block_info’. In the code snippet above, we define a block as an array item ‘curve_block’ and we give this item ‘info’ and determine the ‘cache’. The info defined here will be output onto the blocks page within Drupal.

Following ‘curve_block_info()’ add the following:

/**
* Implements hook_block_view().
*/
function curve_block_view( $block_name = '', $args = array() ) {
    $block = '';
    switch ($block_name) {
        case 'curve_block':
            $block['subject'] = t('Curve block');
            $block['content'] = date("U");
        break;
    }
    return $block;
}

Whenever Drupal request a particular view, ‘hook_block_view()’ checks to determine what the output of that block will be and then forwards on the information requested. As you can see above, we have a switch statement that contains the name of our block that was previously defined in ‘curve_block_info()’, this block has two attributes defined:

  • Subject: This will be output as the header of the rendered block
  • Content: This is the content of the block being output. Here we’re just outputting a simple date stamp, but as blocks become more sophisticated, so too can the output of this content array item.

Save ‘curve.module’ and navigate to the blocks page and you should see the following:

Fig 5

Fig 5

We should now have a block that can be embedded on the page.

Conclusion

In this brief tutorial we’ve covered:

  • Where modules should be placed
  • What are *.info files
  • What are *.module files
  • What are hooks and how can they help me unlock the power of Drupal
  • Creating module help information
  • Creating a custom module block

In later blog articles, we will be delving into greater depth on all of the above, but hopefully this gives you a great foundation to begin your own module development.

If you have any questions regarding the above, or need support for your own custom drupal modules, please get in touch.

Drupal resources:
http://api.drupal.org/api/drupal/modules!block!block.api.php/function/hook_block_info/7
http://api.drupal.org/api/drupal/modules!block!block.api.php/function/hook_block_view/7
http://api.drupal.org/api/drupal/modules!help!help.api.php/function/hook_help/7

Curve
Drupal and UX Design Agency

UK Drupal Agency and UX Design Team with our very own usability testing lab in Leeds. We work with national charities, NGOs and private sector clients.