Recently I found my self in the need to add a configuration page to a custom module in Drupal 7.
This module was used to send daily email notification to the users, but settings like the recipient list email address were hardcoded in the code.
To update this list I was forced to update the code repository and make a deploy on production. So this was not ideal.
So I put my self to the task to learn how to improve the custom module by adding its own configuration page.
Finally it only took a couple of hours to read the relevant documentation, implement the code, and perform the relevant tests.
TL;DR
You can skip directly to the documentation on this links:
- Drupal 7 HowTos - Creating custom modules: https://www.drupal.org/docs/7/creating-custom-modules
- Preparing for a module configuration form: https://www.drupal.org/docs/7/creating-custom-modules/preparing-for-a-module-configuration-form
- Creating the configuration form: https://www.drupal.org/docs/7/creating-custom-modules/creating-the-configuration-form
- Validating the data: https://www.drupal.org/docs/7/creating-custom-modules/validating-the-data
- Drupal 7 form API: https://api.drupal.org/api/drupal/developer%21topics%21forms_api_reference.html/7.x
Prerequisites
You will need a Drupal instance with a custom module already created for witch you also have access to the source code.
How to
All steps are to be applied on the .module
file of your module, except for the step #2 that is to be applied on the .info
file of the module.
1. Adding a new menu item
/**
* Implements hook_menu().
*/
function my_custom_module_menu()
{
$items = array();
$items['admin/modules/my_custom_module'] = array(
'title' => 'My Custom Module configuration',
'description' => 'Configuration for My Custom Module',
'page callback' => 'drupal_get_form',
'page arguments' => array('my_custom_module_admin'),
'access arguments' => array('administer site configuration'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
For this example the custom module name is my_custom_module
, so the hook_menu function name must be my_custom_module_menu
.
- We add a new $items to the menu. The key value is the path to the main menu we want for this new page (in this example
admin/modules/my_custom_module
). - The
page arguments
value points to the function that will be used to populate the form (in this examplemy_custom_module_admi
). We will build this function in the next step. - The
access arguments
value is used to determine who has access to this menu item.
2. Adding a configuration link in the module description
Adding a configuration link on the custom module description page is simple as adding this line to the .info module file:
configure = admin/modules/my_custom_module
This is the same menu path we already used on step #1.
3. Adding items to the form
function my_custom_module_admin($form, &$form_state)
{
// EMAILS Fieldset
$form['my_custom_module_settings__emails'] = array(
'#type' => 'fieldset',
'#title' => t('Email account settings'),
);
// From
$form['my_custom_module_settings__emails']['my_custom_module_settings__emails__from'] = array(
'#type' => 'textfield',
'#title' => t('From address'),
'#default_value' => variable_get('my_custom_module_settings__emails__from', false),
'#description' => t('Email address to be used as FROM and Reply-To.'),
'#required' => true,
);
// To
$form['my_custom_module_settings__emails']['my_custom_module_settings__emails__to'] = array(
'#type' => 'textarea',
'#title' => t('To address'),
'#default_value' => variable_get('my_custom_module_settings__emails__to', false),
'#description' => t('Recipient email address. You can add multiple email addresses by separating them by a colon (,) character.'),
'#required' => true,
);
return system_settings_form($form);
}
Adding items to the form is simple enough using the Drupal form API documentation.
- In this example we can find a fieldset and insde two email fields. The first an input text field for the FORM address, and the second a textarea for multiple recipients email addresses.
- In all the
#default_value
parameters we make use of the Drupal functionvariable_get
to retrieve the last saved value of the field. - The name of the field is the one you specified on the $form array. So, for
$form['my_custom_module_settings__emails']['my_custom_module_settings__emails__to']
the variable name will bemy_custom_module_settings__emails__to
. - The last line
return system_settings_form($form);
will take care to save the form values on submit.
4. Adding custom validating
function my_custom_module_admin_validate($form, &$form_state)
{
$from = $form_state['values']['my_custom_module_settings__emails__from'];
if (!filter_var($from, FILTER_VALIDATE_EMAIL)) {
form_set_error('my_custom_module_settings__emails__from', t('You must enter a valid FROM email address.'));
}
$to = $form_state['values']['my_custom_module_settings__emails__to'];
echo $to;
$to = explode(',', $to);
for ($i = 0; $i < count($to); $i++) {
$address = trim($to[$i]);
if (!filter_var($address, FILTER_VALIDATE_EMAIL)) {
form_set_error('my_custom_module_settings__emails__to', t('You must enter a valid TO email address.'));
break; //Exit the For/Loop on first error
}
}
}
While field parameters like '#required' will take care of basic validation like making a field requiered, some fields may require a more complex check up.
You can add a validation hook with the function name my_custom_module_admin_validate
and add your own validations.
- All form field values will be available inside the
$form_state['values']
. - You can validate multiple fields, and return errors individually by using the Drupal function
form_set_error
.
Thats all. Happy coding!
Top comments (1)
Very nice! I'm familiar with the Drupal 8 Form API, but it's always good to have a Drupal 7 refresher since I'll likely work on Drupal 7 again someday.