Drupal Forms – The form_alter() Hook

What is the form_alter hook?

After following through my first tutorial on forms, you should be able to create a form, check that the input is as you require, and submit the data for processing. But what if you want to add functionality to certain areas of Drupal that you do not control, like contributed modules, or even Core? This is where the form_alter hook comes into play.

Modify Core? Whaaaat?!

Don’t worry! We’re not modifying any of the existing code base! Instead we are using the Drupal hook system to detect a specific action, in this case if a form is being built.

So what does form_alter do?

The form_alter hook does exactly what you think; it allows you to change any form that has been built by Drupal. This means you can add extra functionality to the form, remove certain areas, or load in default data to an existing form. This is the technique used by contributed modules to add extra elements to the Node creation form, and it is exactly what we will do here.

Enough talk, lets code!

OK, so down to business. Here is some example code to add a new fieldset to the node creation form. First off, create your module. You need a .info file, and a .module file. You can look at my input filters tutorial for an example of a .info file.

So once the .info file is set up, create the .module file, and include the following function:

 function test_form_alter(&$form, &$form_state, $form_id) {
		print $form_id;
 }

Now enable your module. Note, do not do this on a production site! Do you see at the top of the modules page, a line saying system_modules? That is the name of the form being printed in the above code. So this is how we know that the form_alter hook is working. Thanks to Drupal’s hook system, the form_alter hook gets invoked on every form, giving us the chance to find the one we want by inspecting the $form_id parameter.

Finding the right form

So, we have a form_alter hook, but how do we target the form we want? Well the best way to do that is to navigate to the form we want, and find its id. Go to your site/node/add/page and find the id being printed (if you want to cheat, the id is page_node_form).

Now we wrap our form id in an if statement to ensure we only target the form we want. (This is a simplistic check for demonstration purposes. It does the job, but not as well as it could. If you want to see the way in which Core handles this operation, simply look in the path.module file).

The full form

So here is a sample form_alter function to add a field to the node form. This should replace the rather simplistic version we previously wrote.

function test_form_alter(&$form, &$form_state, $form_id) {
  if($form_id == 'page_node_form') {
	$form['test'] = array(
	  '#type' => 'fieldset',
	  '#title' => t('Test form_alter'),
	  '#collapsible' => TRUE,
	  '#weight' => 30,
	);
	$form['test']['text'] = array(
	  '#type' => 'textfield',
	  '#description' => t('This is a test to see the form_alter hook in action.'),
	);
  }
}

So as you can see, it’s really that simple! You can easily add new sections to a form. And because $form is passed by reference, the form can be edited and passed back to the Drupal form builder.

Advanced tactics: Chaining submit handlers

So, now we’ve added a field to the form, how do we deal with the data that is provided? The original submit handler does not know about our data, so we need to add a new function that gets called when the form submits. This is called “chaining submit handlers”.

$form['#submit'][] = 'test_node_form_submit';

It’s that simple, but what are we actually doing? The form’s submit button is an array that contains all the functions that will execute on submission of the form. We are simply adding a new function to the array. This function then gets executed in series, so we can then manipulate the data in the $form_state array just like in tutorial 1.

The Full Form

Here's the full code for our form_alter function.

function test_form_alter(&$form, &$form_state, $form_id) {
  if($form_id == 'page_node_form') {
	$form['test'] = array(
	  '#type' => 'fieldset',
	  '#title' => t('Test form_alter'),
	  '#collapsible' => TRUE,
	  '#weight' => 30,
	);
	$form['test']['text'] = array(
	  '#type' => 'textfield',
	  '#description' => t('This is a test to see the form_alter hook in action.'),
	);
	$form['#submit'][] = 'test_node_form_submit';
  }
}

Wrapping it up

So, as you can see, it is very easy to manipulate forms in Drupal, and it allows you to added near limitless customization to Drupal, even to Core forms!

Go forth and enjoy your new-found power!

Tags

Follow on Bloglovin
Top