Learn how to add custom validation to an existing Drupal form

Form validation is an essential part of any web system. You need to ensure that the user has added valid data and if not, show them a meaningful error message. Validation functions are normally implemented in the module where the form is defined. However, thanks to Drupal’s hook system, you can add a validation function to any Drupal form, even if you did not create the form. In this tutorial, you will learn how to add a validation function to the node article form. This is the form where you add content to the article content type and can be found here: node/add/article

Imagine you want to ensure users cannot add the following title: “the quick fox jumped over the lazy dog”. If they do, they should receive an error message and the title field should be highlighted to ensure they know which field has an invalid value.

For this tutorial, you will need to download and enable a module called devel so that you can use its Drupal Print Message (dpm) function.

Alter the form

To add the new validation function, you need to alter the form. You can do this by implementing hook_form_alter(). We covered this in Day 7 of Starting Drupal Module Development. You will need a custom module to implement hook_form_alter. In the example below, I am using the module created in Day 3 of Starting Drupal Module Development. If you have not signed up for it, you can do so here.

In our implementation of hook_form_alter, we will have a look at the validation functions already set for the article node form.

  1. function starting_drupal_dev_form_alter(&$form, &$form_state, $form_id) {
  2. if ($form_id == 'article_node_form') {
  3. dpm($form['#validate']);
  4. }
  5. }

In the above code, we are first checking that the form id is article_node_form. And then, we are calling dpm($form['#validate’]), which will show us an array of the validation functions. $form['#validate’] is a form element which lists all of the validation functions for a given form.

When you hit node/add/article, you will see node_form_validate(), which is the core validator for node forms.

Form validate array

Add a validation handler to the form

You need to add your validation function to that array by adding the following: $form['#validate'][] = ‘starting_drupal_dev_form_validate’. $form[‘validate’] is an array and you can add to that with $form['#validate'][].

  1. function starting_drupal_dev_form_alter(&$form, &$form_state, $form_id) {
  2. if ($form_id == 'article_node_form') {
  3. $form['#validate'][] = 'starting_drupal_dev_form_validate';
  4. dpm($form['#validate']);
  5. }
  6. }

You will see there are now two validation handlers, the core node_form_validate and the one that you added, starting_drupal_dev_form_validate.

Form validate array with new custom validation function

Create the validation function

Now you need to add a function called starting_drupal_dev_form_validate().

  1. function starting_drupal_dev_form_validate($form, &$form_state) {
  3. }

When the form is submitted, the form values will be held in $form_state. To see what is included in form_state(), add dpm($form_state); to the validation function.

  1. function starting_drupal_dev_form_validate($form, &$form_state) {
  2. dpm($form_state);
  3. }

You will then see an array with data from the form you just submitted. We are interested in the values that the user adds to the form, which is held in $form_state[‘values’].

Form state array

In the validation function, you need to check the value of the title field, which is held in $form_state[‘values’][’title’]. If the value is “the quick fox jumped over the lazy dog” then set an error.

Title field in form state array

  1. function starting_drupal_dev_form_validate($form, &$form_state) {
  2. if ($form_state['values']['title'] == 'the quick fox jumped over the lazy dog') {
  3. form_set_error('title', t('You have added an invalid title.'));
  4. }
  5. }

Let’s break down the above function.

  1. if ($form_state['values']['title'] == 'black') {}

This is a simple PHP if statement. If the value of the title field is 'the quick fox jumped over the lazy dog', it will be true and the code inside the if statement will be executed.

  1. form_set_error('title', t('You are not allowed to use "the quick fox jumped over the lazy dog" as a title.'));

The Drupal function form_set_error() is called. The first parameter is the name of the field that has caused the error. In our case, this is the title field. The field specified will be highlighted with a red border, so the user has a clear visual cue as to which field has not validated. The second parameter is the error message, which will be displayed in the message area of the page.

Validation error after user submits invalid title

Make multiple titles invalid

Now let’s take this one step further. Let’s make two phrases invalid, rather than just one. The second invalid title is “birds of a feather flock together”.

To do that, the validation function will become:

  1. function starting_drupal_dev_form_validate($form, &$form_state) {
  2. $invalid_titles = array('the quick fox jumped over the lazy dog', 'birds of a feather flock together');
  3. if (in_array($form_state['values']['title'], $invalid_titles)) {
  4. form_set_error('title', t('You have added an invalid title.'));
  5. }
  6. }

Let’s break this down.

  1. $invalid_titles = array('the quick fox jumped over the lazy dog', 'birds of a feather flock together');

First, we have created an array of invalid titles.

  1. if (in_array($form_state['values']['title'], $invalid_titles)) { .. }

Then we check if the title that the user has added is in that array using PHP’s in_array function. If it is, the if statement will return true and the form_set_error will be set. You can add as many invalid titles as you like to the $invalid_titles array.

And that is all there is to it. There is much more you can do with validation handlers, which we will get into in later tutorials.


Excellent tutorial. Thanks!

i am useing for the Email fields validation it is not Working ,In node email text fields value input time is test@gmail.com
if($form_state['value'][field_email] =='test@gmail.com'){

form_set_error('field_email', t('eamail fields already exists' ));


plz help me any mission

Blair Wadman's picture

Do you have that in a validate function?

Tnx nice...

So nice and pedagogical explanations

Many Thanks :)

You just saved my sanity. I'd been using conditional fields to change both the display of some fields and their requirement status based on user input in another field, but that worked only to control the display and to set the appearance of being required (the red asterisk). It didn't actually enforce validation, and I spent much of yesterday trying various suggested solutions. This is the only one I've found that works. Thanks!!! Very well explained.

Blair Wadman's picture

Glad it helped!

Thanks for match

This works great! Thank you! I would like to use the custom validation in addition to the normal node edit form validation, but it seems to replace it. How do I call the normal form validation as well?

Oh, please disregard my previous comment. This is working fine! Thank you!

when i adopt this tutorial in an own module i get WSOD and PHP-Error.

My Code:

  1. function MEIN_MODUL_form_alter(&$form, $form_state, $form_id) {
  3. if ($form_id == 'sedcard_node_form') {
  5. function custom_form_validate($form, &$form_state) {
  6. dpm($form_state);
  7. }
  9. $form['#validate'][] = 'custom_form_validate';
  10. #dpm($form);
  11. #dpm($form['#validate']);
  12. }
  13. }

In Server-Error.log i get this:

  1. PHP Fatal error: Call to undefined function custom_form_validate() in /var/www/dom7/includes/form.inc on line 1519, referer: http://www.domain.com/node/100037146/edit

Is this tutorial not up-to-date or what i made wrong?

Blair Wadman's picture

The tutorial was written in 2013. It should still work fine though.

It appears that you have the function custom_form_validate($form, &$form_state) nested inside MEIN_MODUL_form_alter(). These should be separate functions.

This has been very useful. Thank you for taking the time to do it.

Awesome! Very well explained.

Clear and simple. Thank you!

Would this be usable to deal with verifying whether a user has previously submitted a form on a specific node? I have a form used in every instance of a specific content type which the user would click to acknowledge they have read and understood the info in that specific node. I am trying to limit submissions to one per user per node. I am assuming the Submitted boolean $form_state refers to the <em>current</em> submission and not previous submissions, which is what I would need to validate against.

Add new comment