There are many reasons why you might want to add extra validation rules to a Drupal form. This is a simple tutorial on how to add a validation function to an existing form that is generated from a module that you have not created yourself. It could be in a core or contributed module.

The problem

A form has been created by another module, but we need to add additional validation.

The solution

1) Use hook_form_alter to alter the form and add an additional validation function

<?php
/**
 * Implementation of hook_form_alter().
 */
function my_module_form_alter(&$form, $form_state, $form_id) {
 if ($form_id == 'example_form_id') {
  array_unshift($form['#validate'], 'example_validate');
 }
}
?>

array_unshift will add the validation function to the beginning of the $form[‘#validate’] array. This is helpful if you require other validation function to process after your new one. For example, if the form is the user login form (form ID is user_login), then the user_login_final_validate function should happen last. Therefore, we wouldn’t want to add a validation function to the end of the $form[‘#validate’] array.

If it doesn’t matter if the validation function goes at the end of the $form[‘#validate’] array, then the standard way to add a validation function is as follows:

$form['#validate'][] = 'example_validate';

2) Add the custom validation function

/**
 * Validate profile form
 *
 */
function example_validate ($form, &$form_state) {
  //perform some validation logic
}

Working example

As an example, I want to add extra validation when a user changes his/her email address. If the new email address is the same as their existing email address, I want the form to not validation and display a validation error (since the user should add a different email address).

/**
 * Implementation of hook_form_alter().
 */function my_module_form_alter(&$form, $form_state, $form_id)  {
 if ($form_id == 'user_profile_form') {
  array_unshift($form['#validate'], 'email_check_validate');
 }
}

/**
 * Validate profile form
 * Force form error if new email address matches current email address
 *
 */
function email_check_validate ($form, &$form_state)  {
  global $user;
  $old_email = $user->mail;
  $new_email = $form_state['values']['mail'];
 
  if ($old_email ==  $new_email) {
    form_set_error('mail', t('Your email could not be changed'));
  }
}

In the above validation function, I am comparing the user’s current email address, as defined by the user object of the current logged in user($user->mail), with the new email address from the form itself ($form_state[‘values’][‘mail’]). If they match, the user has entered the same email address as their current email address, therefore the form does not validate and the user receives an error message.