Create your first Drupal admin interface

One of the key features of a Drupal module is an admin interface. An admin interface enables you to make a module's settings configurable by a site editor or administrator so they can change them on the fly.

You may be tempted to hardcode settings in your module or theme, but if the site editor wants to change the settings in the future, they will have to come to you. You will then need to make the change and deploy it. I'm sure you'll have more interesting things to do than making simple setting changes! One of the reasons why you would use a flexible CMS like Drupal in the first place is so that such things are editable without the need for a code change.

The example we are going to use to create the admin settings interface is a module which displays a message to users when they login. The message itself will be configurable in the admin interface.

Module Setup

The first step is to setup the module itself. The module is called Welcome.

Steps to create the module:

  • Create a folder inside “sites/all/modules/custom” called “welcome”.
  • Create a file called “”
  • Create a file called “welcome.module”

In, add the following:

  1. name = Welcome Module
  2. description = Display a configurable welcome message when users login
  3. core = 7.x
  4. files[] = welcome.module

In welcome.module, add the following:

  1. <?php
  2. /**
  3.  * @file
  4.  * Module file for Welcome Module
  5.  */

Now enable this module in the module page (or using Drush).

Display a message when a user logs in

To do something when a user logs in, you need to implement hook_user_login(). Here is the basic implementation of hook_user_login():

  1. /**
  2.  * Implements hook_user_login().
  3.  */
  4. function welcome_user_login(&$edit, $account) {
  5. }

Hook user login takes two arguments, $edit and $account.

$edit Form values submitted by the user on the user log in form
$account The user object for the user that is logging in

To display a generic message to all users, you could simply add a drupal_set_message() inside the implementation of hook_user_login().

  1. /**
  2.  * Implements hook_user_login().
  3.  */
  4. function welcome_user_login(&$edit, $account) {
  5. drupal_set_message('Thank you for logging in and welcome!');
  6. }

And here is the message that users see when they login.

The welcome message displayed to the user

The Admin interface

Now you need to make the message configurable. For that, you need an admin interface with an admin form where the welcome message can be edited. The first step is to create a path for the form, which is where editors will access the form. In welcome.module, you need to implement hook_menu().

  1. /**
  2.  * Implements hook_menu().
  3.  */
  4. function welcome_menu() {
  5. $items['admin/config/people/welcome'] = array(
  6. 'title' => 'Welcome message configure',
  7. 'page callback' => 'drupal_get_form',
  8. 'page arguments' => array('welcome_form'),
  9. 'access arguments' => array('administer users'),
  10. 'type' => MENU_NORMAL_ITEM,
  11. );
  13. return $items;
  14. }

In the hook_menu() implementation above, you are creating a new path: admin/config/people/welcome. This will be available to users who belong to a role with permission to administer users.

The page callback is the function that is called as part of the request for the path. In other words, when a user hits admin/config/people/welcome in the browser, the callback function will be called. You can define a custom callback function but in this case you are calling drupal_get_form(), which is a built-in Drupal function that uses the Form API to build a form.

Form API

With any page callback, you can pass page arguments to it. An array of arguments will get passed to the callback function. When you use drupal_get_form as the callback function, you need to pass the form ID as the argument. In this case, you are using ‘welcome_form’ as the ID of the form. You can use anything you want as the form ID as long as it is unique. Best practice is to include the module name as the first string of the form ID to ensure uniqueness. Spaces and hyphens are not allowed in form IDs.

drupal_get_form() will return an array which another built in function, drupal_render(), will convert into a rendered HTML form.

Drupal's hook menu maps to the callback function
Figure 1: Menu page argument matches implementation of hook_form().

The form needs to provide a textarea for users to add and edit the message that is displayed to users.

Here is the function welcome_form, which defines the form:

  1. /**
  2.  * Admin form to configurable welcome message
  3.  */
  4. function welcome_form($form, &$form_state) {
  5. $form['welcome_message'] = array(
  6. '#type' => 'textarea',
  7. '#title' => t('Welcome message'),
  8. '#rows' => 5,
  9. '#required' => TRUE,
  10. );
  12. return system_settings_form($form);
  13. }

This is a very simple and small form, with just one field. A form is defined using a multidimensional array. Each element of the form array has its own key. So $form[‘welcome_message’] is the key for the field. This becomes the name of the element in the final rendered HTML form. The key must be unique.

Each form element is in itself an array with attributes. The attributes we are defining here are:

#type - The type of field. Can be textarea, textfield or select
#title - The title of the field
#rows - With a textarea, you can define how many rows it has
#required - If required is set to TRUE, this field is required and a validation error will occur if the user submits the form with

Attributes and properties begin with a hash (#).

In the return statement, $form is passed through another function, system_settings_form(). This handy function takes care of common tasks that are needed for any admin form, such as submit buttons and saving form data to the database.

Go to the path admin/config/people/welcome and the form should look like this:

The welcome message admin form
Figure 2: Welcome message form

The following graphic illustrates the process Drupal goes through to build the admin form.

How Drupal builds the admin interface
Figure 3: Admin form building process

You may be wondering, what happens to the data after the form is submitted? I mentioned that system_settings_form() takes care of saving form data but where is it stored?

Data from admin forms is stored in a special Drupal database table called variable. By using system_settings_form(), you are telling Drupal to automatically store the data from this form in the variable table. The variable table has just two columns, name and value. Open up the database and take a look.

The Drupal variable table
Figure 4: Variable table

At this stage, there is no variable for welcome_message. That is because you have not submitted the form yet. Go ahead and add a message and submit the form. Refresh the variable table, you will see a welcome_message variable.

When using system_settings_form() the name of the variable matches the element key in $form.

The Drupal variable table with the welcome message
Figure 5: welcome_message form key matches variable name

Setting defaults

After you submitted the form, you may have noticed something odd. The textarea is blank. That is going to be annoying if you want to edit the form again and can’t remember what you entered last time. This is very easy to fix. All you need to do is get the variable from the database and use it as the default value.

  1. function welcome_form($form, &$form_state) {
  2. $form['welcome_message'] = array(
  3. '#type' => 'textarea',
  4. '#title' => t('Welcome message'),
  5. '#rows' => 5,
  6. '#required' => TRUE,
  7. '#default_value' => variable_get('welcome_message', ‘welcome’),
  8. );
  10. return system_settings_form($form);
  11. }

variable_get() is a built-in Drupal function that will get any variable. The first argument is the variable name. The second is a default value, which will be used if the variable does not yet exist in the database. The default value is required, so you need to add something.

And finally, you need to display the saved message to users when they log in. To do that, change welcome_user_login() to the following:

  1. function welcome_user_login(&$edit, $account) {
  2. $message = variable_get('welcome_message', 'welcome');
  3. drupal_set_message(check_plain(t($message)));
  4. }

You are retrieving the stored message from the database using variable_get(‘welcome_message’,’welcome’). If the variable has not been set yet, then Drupal will use the default value of ‘welcome’. Drupal displays the message using drupal_set_message(). The message is passed through the check_plain() and t() functions to handle security and translation.

And that is it! The welcome message is now fully configurable in an admin interface.

The welcome message displayed to the user

Continue learning

If you liked this tutorial, you'll enjoy my book, Master Drupal Module Development. If you want to learn more about how to develop your own Drupal modules, check it out.


You should check_plain $message.

Blair Wadman's picture

Good spot! Added to the post.

The first step in this was to create a folder in "sites/all/custom" shouldn't it be "sites/all/modules/custom"?

I've always just put all the modules together but this is a much more logical way especially because I've only got a few modules that I create for clients and it is a much easier way to find them.

Blair Wadman's picture

Yes you correct, it should have been "sites/all/modules/custom". Updated now, thanks for spotting that!

Actually, drupal_get_form has only $form_id (as in drupal_get_form($form_id) from Drupal API) and that seems sufficient.

This function should be used instead of drupal_build_form() when $form_state is not needed (i.e., when initially rendering the form) and is often used as a menu callback.

Other function, has form_state, drupal_build_form($form_id, &$form_state and is considerably more versatile.

This is a great tutorial. However, it seems that the argument for the form hook has changed from $form to $node, unless I am mistaken.



Blair Wadman's picture

Hi Joe,
Node editing forms use $node, but this is a system configuration form, so it still uses $form (there is no node to edit). I think the confusion comes from the example code snippet referring to hook_form() - hook_form() is actually a node edit form hook, so I've removed implements hook_form() from the code snippet and need to remove it from the graphic as well.

Nice tutorial, and it really helped me to create my first Drupal admin interface to make my drupal module.
I am really thankful.


New comments for this tutorial have been turned off.