Module Development for Drupal 7

This page is archived

We're keeping this page up as a courtesy to folks who may need to refer to old instructions. We don't plan to update this page.

Alternate resources

"There's a module for that."

You've probably heard this before and many times you can find a module that provides the functionality you need — or at least pretty close to what you need. Drupal's contributed module projects number in the thousands, but what if there isn't a module for what your use case? You just might need to build a module for that.

In this series, you will learn about the tools and resources available to Drupal developers, including where to find documentation and what APIs are available to you, both on drupal.org and api.drupal.org. We'll take a look at the Devel module and learn how to use it to inspect the variables, objects, arrays and other things at work under the hood of Drupal 7.

You'll build several different modules that explore and interact with Drupal's various systems and API, including:

  • Form API
  • Menu system
  • Hooks
  • Render API
  • Theme system
  • Database API

Over the course of this series you'll be able to:

  • Describe the anatomy of a module
  • Implement common hooks
  • Write more secure code
  • Interact with Drupal's menu system
  • Create and alter forms
  • Peform CRUD operations on a database

This series starts with the basics and moves you step-by-step to more advanced concepts. Even if you are quite comfortable with PHP but are struggling to understand how to appropriately interact with Drupal 7's API, the lessons in this series can help you develop "The Drupal Way."

Tutorials in this course
More information

"There's a module for that."

You've probably heard this before. Many times you can find a module that provides the functionality you need — or at least pretty close to what you need. Drupal's contributed module projects number in the thousands, but what if there isn't a module for your use case? You just might need to build a module for that.

In this series, you will learn about the tools and resources available to Drupal developers, including where to find documentation and what APIs are available to you, both on drupal.org and api.drupal.org. We'll take a look at the Devel module and learn how to use it to inspect the variables, objects, arrays and other things at work under the hood of Drupal 7.

You'll build several different modules that explore and interact with Drupal's various systems and API, including:

  • Form API
  • Menu system
  • Hooks
  • Render API
  • Theme system
  • Database API

Over the course of this series you'll be able to:

  • Describe the anatomy of a module
  • Implement common hooks
  • Write more secure code
  • Interact with Drupal's menu system
  • Create and alter forms
  • Peform CRUD operations on a database

This series starts with the basics and moves you step-by-step to more advanced concepts. Even if you are quite comfortable with PHP but are struggling to understand how to appropriately interact with Drupal 7's API, the lessons in this series can help you develop "The Drupal Way."

Additional resources

Devel module at Drupal.org

More information

In this video Joe Shindelar provides a quick overview of the minimum set of tools you'll need in order to get started with module development. Some kind of web server to host your development site on, an editor that allows you to edit PHP files (preferably one with syntax highlighting), a MySQL client, and Drush. Learn about how these essential tools fit in the module developers tool belt and then download and install a bare bones copy of Drupal to start tinkering with.

More information

This video walks through the handy devel module from http://drupal.org/project/devel and demonstrates the tools it provides for debugging, inspecting and analyzing the code and SQL queries happening on your site. In this video you'll also learn about some of the helper functions built into the devel module that make it simpler to inspect the large nested arrays that you'll commonly come across when writing code for Drupal.

You may not have heard of the function dsm() before now. It is a legacy function and dpm() is the newer name. The two functions are identical since dsm() is just a wrapper for dpm().
The idea is that dsm() was a poor name for the function, it's short for drupal set message, but what was later decided that drupal print (as in print_r) message was better.

The difference between those two and kpr() is that dpm() does a permissions check to make sure the current user has permission to view devel's output, and then puts the krumo'd variable dump into the message queue via drupal_set_message(). This means that dpm() will work and let you see the output even if you're redirected. Great for debugging forms. kpr() just krumo's and dumps the value right here, right now. No permission check, no regard for where the content is being spit out.

More information

In this video you'll learn how to use api.drupal.org the canonical source for information about Drupal's hooks, APIs, and code documentation in order to find out information about implementing a particular hook, making use of a particular function or library of functions, and even gaining a better understanding of some of the big picture concepts behind Drupal's code and APIs.

More information

Walks through some of the basics elements that are required and common for all Drupal modules. Then we create a simple demo module to see how it works.

More information

This chapter describes how Drupal modules are able respond to specific events through the hook system. A couple of example hooks are implemented in order to see how this process works. This video builds on the demo module we created in the previous chapter.

More information

When writing code for the web it is very important that you pay attention to security. Drupal provides many tools to help you out and in this presentation we'll look at what those are and how to make sure you use them properly.

Additional resources

Sanitization functions
Writing secure code

More information

Provides a overview presentation for how Drupal's menu system takes care of incoming requests via the index.php. Then it walks through the process of implementing a simple module that hooks into Drupal's menu system at the path of /magic. It then executes a page callback function of menu_magic_basic(), which outputs some simple markup text.

Additional resources

hook_menu() documentation

More information

This chapter goes through the process of passing a wildcard variable to a function via an argument from the URL. It creates a MENU_LOCAL_TASK tab on the node which inverts the text to display upside down. It uses a page callback function that is included within a separate file in order to save on how much memory is used.

More information

This chapter walks through the process of adding links to the contextual drop-down widgets new in Drupal 7. It also shows how using menu autoloaders can help simplify the code that you write in your page callback function since you won't have to do extra checking on the data.

As a note, if you are wondering why we started our function with an underscore (_), naming functions with an underscore in front of the name is a common convention in Drupal that sort of implies that "this function is for internal use by this module only" and shouldn't be called by itself. It's also a nice way to ensure that your internal functions are not colliding with the namespace of a hook or another module. Here's a good blog post about naming things.

More information

This video walks through the basic use of Drupal 7's Render API for outputting content, and gives some hands-on experience in navigating and working with renderable arrays. We expand the Menu Magic module by creating several different kinds of page elements to show how renderable arrays work.

More information

This chapter walks through how you can conditionally add either JavaScript or CSS to a content element as well as how to cache the content with Drupal's caching system. Additional notes: The cache will clear the first time cron.php is run AFTER whatever time you've specified as the cache expiration date in your code. Which you could easily calculate to be 30 seconds in the future and then store that timestamp in the database. However, you would also need to make sure that cron was running frequently enough to clear the cache every 30 seconds.

Additional resources

Render Arrays overview (Drupal.org)

More information

This video walks through how to use the new hook_page_alter() in Drupal 7 by transforming an unordered list into an ordered list. Because all of the content, region & blocks are stored within a renderable array before being output to the page, then this new hook allows modules and themes to make changes to page before it is fully rendered.

More information

This video shows how a module can integrate with Drupal's theme system by exposing a new themeable item to the theme registry with hook_theme(), and then creates a function in order the customize the output of that themeable item. The then video demonstrates how the theme layer can override the markup defined with theme functions at the module layer.

More information

This presentation provides an overview of the different phases of the form submission and validation process that Drupal uses with the Forms API. This will give you a good foundation for implementing forms yourself in the following videos.

More information

This videos goes through the process of creating a form with Drupal Forms API that is single select list that has a validation, submission and redirect functionality.

NOTE:

Their is a typo in the code displayed in the video. The function

function form_fun_cake(&$form_state)

is missing the $form paramater and should instead be

function form_fun_cake($form, &$form_state)

Curious about when you're supposed to translate "title" and when you should leave it alone? Here's the answer: You don't need to translate the 'title' attribute of an array that defines a menu item because Drupal will take care of that automatically. In fact, you shouldn't translate those as they'll end up getting double translated if you do. This is because Drupal end's up using this string of text in a number of different ways some of which don't actually need to be translated and others that do like for example when it's the title of a page or the text of a link in the menu system. The #title (and #description) property for elements in Form API array however are your responsibility to translate.

More information

This chapter shows how to cluster different form elements into fieldsets as well as how to expand the Forms API renderable array a tree that preserves the structure and hierarchy of the form. We'll expand the Form Fun example module and talk about the #tree property. This video uses krumo() and dsm() functions. You will need to download, install, and enable the devel module to use these functions. These functions allow you to see what variables are available to you. To accomplish the same task without using the devel module, you can add the following snippet to your module: drupal_set_message('' . print_r($vars, true) .'');

 

Note: There is a typo in the code used in this video. The function form_fun_tree() is missing a parameter, and should be as follows function form_fun_tree($form, &$form_state).

More information

This video shows the basic syntax for creating form dependencies with the states system. For a more information about the states system, then be sure to check out JavaScript form dependencies with the States System.

Note: There is a typo in the code used in this video. The function form_fun_states_form() is missing a parameter, and should be: function form_fun_states_form($form, &$form_state).

More information

This video goes through the process of changing some of the properties of a form with the hook_form_alter() function. This hook is a very powerful tool to be able to modify existing Drupal forms, created by core or contributed modules, and tailor them to your needs.

More information

This video shows how to target a specific form with the hook_form_FORM_ID_alter and creating a customized validation function for a form.

Note: There is a typo in this video. (The code is correct in the downloadable example file attached to the previous video.)

In the demo_validate_password() function, the following line shown in the video if (in_array($form['values']['pass'], $badpasswords)) { should be if (in_array($form_state['values']['pass'], $badpasswords)) {.

More information

This video goes through the process of creating a configuration form in order to save settings to the variables table in the database, and how to integrate those variables into your module.

Correction

The $item array in the function demo_menu() should be named $items, to match the return $items; line. (Either that or return $items; should be fixed to return $item;.) Just make sure the array you are building matches the name of the variable you are returning.

Additional resources

Form validation in Drupal

More information

In this excerpt from the Overview of Drupal 7, Angie Byron, talks about the Database API in Drupal 7. This was a round table discussion with other Lullabots on the line who ask and answer questions, in addition to Angie's presentation. This lays a good foundation for how the database system works in Drupal and sets you up for the hands-on tutorials that follow.

Additional resources

Database API documentation

More information

In this chapter we learn how to get data out of the database and display it. The example walks through writing a module that creates a page that displays how many nodes are published and unpublished for each content type in our site. We use the db_select() function to accomplish this.

More information

In this chapter we learn how to create a new database table. This example walks through creating a module that defines the the properties of our new table and also programatically creating that table. We learn about hook_schema() and hook_update_N() in our module's install file.

Trainers note: This video starts out with a module that implements hook_node_view() and stores data about views in the $_SESSION variable. It also states that we built this earlier in the series. However, that's not true. We did talk about hook_node_view() in https://drupalize.me/videos/event-driven-hook-system, but we never actually wrote the $_SESSION handling part. So, if you're following along and want the same sample code we start with make sure you download the code attached to this node.

More information

In this chapter we learn other ways to interact with our database beyond the simple db_select() query from the earlier video. This example walks through writing a module that that saves and displays data about how many times a user has visited a specific page. We learn about db_select(), db_insert(), db_update(), db_merge(), db_delete() and introduce the concept of "get and set" helper functions.

More information

In this chapter we learn about changing the definition of a database table after it has already been installed. This example expands on the previous chapters by adding a new field to the table to collect the date a user last visited a node. We learn more about hook_update_N() as well as db_add_field().

This course appears in the following guides:
Module Development
A guide to module development in Drupal 7.

Legacy Module Development