A really simple Drupal 7 example module

I developed this module back when I managed my self-hosted Drupal system. Since then I’ve found that there’s more to life than managing your own web site, and that it’s cheaper and more effective to do it through WordPress.com even though I retain a fondness for Drupal. Yes, it’s ironic that this Drupal example is hosted on a WordPress server.

A couple of months back I attended DrupalCamp Twin Cities, to try to improve my understanding of Drupal. It was a good event and, thanks to an enlightening talk by Tess Flynn, I now see how the incoming path is converted into code execution.

This week I took the next step: I wrote the simplest possible Drupal 7 module from scratch. Although I had several examples to work from, it took several attempts to get things right. And now, here it is: Rick’s Testie Drupal 7 Module (zip file).

What the Testie Module Does

Testie does as little as possible while doing something we can see and understand.

Specifically, you type in the URL http://example.com/testie (for whatever the site’s domain name is) and the module creates a page with some text on it. In this example the text says:

This is my testie demo page.

The text “This is my testie demo page.” is produced by the function called when the “/testie” URL is retrieved.

If we wish to generate a customized page of some sort, we simply revise the function to generate different outputs.

The Basics

The simplest Drupal 7 module consists of two files: an information file and a program file. To turn the files into a module, you place them in a common directory and compress them into a Zip or Tar file. Part of the trick is to use the right names for everything.

To keep things as simple as possible, I named everything “testie” – the module, the common directory, the files, the functions, and so on. Here is the file organization:

  • testie (directory)
    • testie.info (information file)
    • testie.module (program file)

The .info file provides the text you see in the site’s Module list. It also identifies the program file(s) and the compatible versions of Drupal. Here is the text of the example:

name = Testie Demo
description = "Rick's testie module - a very simple module demo"
core = 7.x
files[] = testie.module

The “name” appears as the module name in the module list, with the “description” appearing as a paragraph to the right of the name. According to legend, every source code file contained in the module should have its own line of text similar to the line above beginning with “files[].” I haven’t puzzled out the file naming conventions in detail. Clearly, it’s OK to have a single program file with the module’s name, as shown.


The program file traditionally begins with an opening php tag, and then a comment to summarize the file’s contents. The minimum file contains two functions, a “menu hook” and a content-generating function.

In Drupal, there are two “menu systems.” One is the obvious mechanism that manages the menus that appear on the site’s pages. The other menu system selects the right function to call based on the path appearing in the URL. A module’s “menu hook” function gives Drupal at least one path/function pair.

The content-generating function outputs text to place on the resulting web page.


 * @file
 *testie - Rick's demo module
 * By Rick Smith ofCryptosmith
 * This thing is too trivial to deserve protection
 * through "intellectual property rights."
 * This is my first attempt to write Drupal code
 * and I probably don't have the format quite right.

/* the menu hook - adds the path "/testie" to the site. */

function testie_menu(){
 $items['testie'] = array(
 'page callback' => 'testie_my_page',
 'access arguments' => array('access content'),
 return $items;

/* this code (noted in the callback above) creates the
 * contents of the "testie" page */

function testie_my_page(){
 return "This is my testie demo page.";

The two functions in this example provide the menu hook and the content generation, respectively.

The testie_menu() function defines the page name “testie” and ties it to the execution of the testie_my_page() function. Access to the page name “testie” is granted to everyone who has “access content” rights on the web site (which is generally everyone).

The testie_my_page() function simply returns a paragraph of text that is rendered on the resulting page.


Drupal cognescenti seem to consider the installation process to be too trivial to describe clearly. There were hints in the regular instructions, but I really had to rabbit-hunt through the documentation to find the essentials.

With Drupal 7, though, module installation is a lot simpler and almost automatic. You go to the “Add Module” page and either upload the zip/tar file, or you provide its URL. Again, here’s the link:

Once your site has uploaded the module, you’ll need to activate it from the Modules page. It appears with the “Other” modules.

If you want to look at the Testie code, simply download the module file and uncompress it. You’ll get the testie directory containing the two files shown above. Or, if you want, you can simply transcribe the source text shown above into two files, compress them, and now you have your own module.

If you’re hardcore and really need to use FTP, then the secret is to add modules to the “sites/all/modules” directory. The top-level “modules” directory is reserved for the core modules distributed with Drupal. Notably, its contents will be wiped out and replaced each time you upgrade. You really want to avoid storing customized things in there.

Instead, all of your separately-downloaded modules go into the sites/all/modules directory. (Apparently you can create site-specific directories if you’re using the same Drupal installation to support multiple different sites, so that’s why there’s this “all” directory.) If your installation doesn’t yet have the “all” directory, or it doesn’t contain a “modules” directory, go ahead and create it.

Some folks recommend creating another directory inside “modules” if you create your own modules. It’s optional but Drupal can handle it.

So, once you have the appropriate directory created, you do the following to FTP the new module:

  1. Unzip/untar the files. This should create a directory that contains the module’s files.
  2. Copy the directory and its contents to the sites/all/modules directory of your web site
  3. Go to the “admin/modules” URL to see the list of modules.
  4. Click the new module’s check box to enable it. Do the same for other modules you need to enable.
  5. Click “Save configuration” at the bottom of the module page. Nothing happens till it’s saved.
  6. Once the page has refreshed, the module should be active. If the module makes changes to the site’s database, you should run the “update.php” script to make sure the database is up to date.

The “testie” module doesn’t use the site database at all, so you don’t need to run the update script after installing it.