You are here

Create your first simple Drupal custom module

In this tutorial, you'll learn how to create a simple custom Drupal module.  Our specific use-case will be to modify the default search page on our site.

Setup folder structure

Drupal sites have the following folder structure for storing/accessing modules



Any contributed or custom modules you want to use on your site will either go into the 'all' sites modules directory, which means it will be available to be used by *any* site in this particular drupal installation, or it can go into a certain site's modules directory (the default site or any other site), which means it will only be available to be used by that particular site in this drupal installation.

In our case, we'll put our custom module under the /sites/all/modules directory for all sites to use (I actually only have one drupal site on my installation anyway).

Usually, to be even more organized, I create /contrib and /custom sub-directories in both my /modules and /themes folders to keep track of contributed modules and themes I'm using (those go under /contrib) and custom ones I've created (which go under /contrib).  Feel free to create that sub-structure as well.

This is what my modules folder structure will look like as we begin creating our new module:



To get started, let's create a new folder under /sites/all/modules/custom in our drupal site and call it "search_enhance":

Module folder structure

.info file


Next we have to create our mandatory module .info file.  The .info file of a module contains meta information about your module, and announces the module's existence to Drupal.  As soon as you create your .info file (and it's in one of the anticipated module locations from above), it will be found by Drupal, and your module will be included in Drupal's module list on your site.

Write it

In our module's folder (search_enhance), create a text file called

Here is the content of our simple module's .info file:

name = Search Enhance
description = This module modifies the default search page (not the block).
core = 7.x

This is the bare minimum for a .info file.  Let's go through all the lines

  1. The name and description are what will be listed in your site's modules list
  2. The core is which version of Drupal the module is relevant for.  Different versions of Drupal have very different apis and functions, so our module has to specify which version it was written for.

To see more complicated .info files, which include 1) dependencies (if your module works with another module and needs to list that as a site pre-requisite or dependency) or 2) which package or section of the module's list it should appear under, look at the .info file documentation on

Test it

Before we can test this part out, we'll also have to create our module's .module file which will include our entire module implementation.  For now, just create a blank text document called 'search_enhance.module' and save.  Now we can test!

Go to our site's /admin/modules page and see if our new module is listed!  It should use the exact 'name' and 'description' we used above, and it should be in the 'Other' section, since we didn't specify any other package name in our .info file.  If you want, make any edits you want to the above, even include a package, and refresh the page to see the changes (may need to clear cache too).  Also, look into the .info file documentation to see how you can add a version to our new module.  As you can see, it's the only one on the list that doesn't have a version yet.  You can call our first version 7.x-1.0.  Just add the line 'version = 7.x-1.0' at the end of the .info file.

The thing is - our module won't actually do anything if we enable it at the moment, so let's keep going before we enable it quite yet.

.install file


A .install file is typically used to create any necessary database tables if your module actually needs to use any new tables to store its data.  It has, typically, hook_schema() and hook_install() functions, in which it sets up the necessary tables it needs to store its data - it may even create some variables, and a hook_uninstall() which remove its tables and variables. 

In our simple module, we will not need to have any custom database tables or variables, so we will not create a .install file!  Let's move on to the .module file...

.module file


In our case, our entire module's implementation will be in this single .module file.  As you get more experienced with writing custom modules, you'll realize that there are some best practices for having multiple folders with implementation files when your module gets large and complicated.  For example, many large modules separate out the code to build the admin ui into a separate file, etc.  In our case, we only implement two functions, and don't even have an admin UI, so we will put everything into a single .module file...

Write it

So we've already created a search_enhance.module file in our module's folder.  Here is the first function we will implement:


//function search_enhance_form_search_form_alter(&$form, &$form_state, $form_id) {
function search_enhance_form_alter(&$form, &$form_state, $form_id) {

  if ($form_id == 'search_form') {
  // Set page title
  drupal_set_title("My customized page title");
  // Customize some aspects of the search form.
  $form['basic']['keys']['#title'] = t('Keyword(s)');
  $form['basic']['submit']['#suffix'] = '<div class="search_help"><a href="/search_help .node .content"      rel="lightmodal[|width:420px; height: 220px;]" title="Search Help">Search help</a></div>';


As you can see above, in Drupal, you should start your implementation files with a "<?php" at the top, but do not include  a closing "?>" tag at the end of the file.

Our simple module implements a single function called hook_form_alter().  This popular hook in Drupal can be implemented by any module to alter any existing drupal form.  In our case, we want to alter the search form that Drupal has by default.

First, visit the default Drupal search page on your site at  This is the form we'd like to customize a little bit.  To implement hook_form_alter(), you need to

  1. Replace the word 'hook' with your custom module's name.  In our case, this function will be called 'search_enhance_form_alter'.  This is what you have to do for all hook implementations in Drupal
  2. Find the name of the form you want to modify, so we can set an appropriate if() in our hook_form_alter.  Of course, you can always use the hook_form_SPECIFIC_FORM_ID_alter() hook instead, but I chose not to for this example.
    1. To get the name of the form, let's look at the page source and find that specific form in the page's html
    2. I can see that the html code for the form is
      <div class="content">
      <form id="search-form" class="search-form" accept-charset="UTF-8" method="post" action="/search/node">
    3. So the id of the form is 'search-form' and that's what we put in our form id if() check above!

The remainder of the module does three things if it finds that the form we're currently displaying is indeed the form with id="search-form"

  1. It sets the page's title to "My customized page title"
    • That's just "Search" by default
  2. It changes the label on the form to "Keyword(s)"
    • That's "Enter your keywords" by default
  3. It adds a suffix after the submit button which places a link called 'Search help' after it.  This is just a little fun something I wanted to add.  If you create a page with a path of '/search_help' on your site and have the lightbox2 module installed, this will pop up the contents of that page into a light modal!  I have this functionality on one of my sites, and it's neat because site editors can change the contents of the search_help page with new examples and tips whenever they want to...  Feel free to delete this line if you don't have lightbox2 or don't want to create a new /search_help page...
  4. That's it.  Now that you understand the code a little better, let's test.

Test it

Before we enable our module, here's what Drupal's default search page (/search/node) looks like:

Now, go back to the module's list and enable our new module.  Here's what the search page will look

Congratulations on creating your first custom Drupal module!  Now go do more cool things!


  • This will not modify the search block!  The form id for the search block, if you look for it in the page source, is actually "search-block-form", so our module will not run on it!
  • I obviously would want to apply some css styling on the 'Search help' link to move it away and/or make it into a button, but just didn't want to go that far for this simple example.  :-)



I have created a custom module (i have named it first) in the same way you have elaborated but it's not showing in modules.My is as:
description=my first custom module
and .module file is blank....any help will be appreciated...Thank you

I'm assuming you've cleared your cache and that your custom module is in one of the accepted modules locations, such as /sites/all/modules or /sites/all/modules/custom... Also, make sure you name the .module file 'first.module' and give it the <?php opening tag (even if it's blank). 

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.