Last updated September 2, 2012. Created on April 14, 2006.
Edited by Gaelan, xamount, Steve Dondley, pwolanin. Log in to edit this page.

When using Forms API to alter an existing form, if you add your own items you need a way to get the data back. When doing this to the node or user form, this is easy, but not so easy when modifying some of the more obscure forms.

Drupal 5

In this case, you need to add your own hook into the _submit chain. To be able to identify the form from within your submit handler, you need the form id ($form_id) submit data, you need the form values ($form_values). Both are automatically passed to your submit handler by the Forms API.

In your hook_form_alter():

<?php
  $form
['#submit']['my_very_own_submit'] = array();
?>

And your submit function prototype:

<?php
function my_very_own_submit($form_id, $form_values)
?>

Additional parameters

You can, if desired, pass additional parameters to your submit function. Your hook_form_alter() would then be like this:

<?php
  $form
['#submit']['my_very_own_submit'] = array($parameter_three, $parameter_four);
?>

And your submit function prototype:

<?php
function my_very_own_submit($form_id, $form_values, $parameter_three, $parameter_four)
?>

Getting your submit function called first

If you'd like to alter user input before it gets saved to the database, you'll want to force your submit function to the top of the $form['#submit'] array like so:

<?php
$form
['#submit']['my_very_own_submit'] = array();
$form['#submit'] = array_reverse($form['#submit']);
?>

Drupal 4.7

In this case, you need to add your own hook into the _submit chain, but how to do this isn't entirely straightforward, because you have to provide the hook with the arguments; one of these arguments needs to be a reference to $form_values, which you don't have yet. Or do you?

Turns out, forms API actually does provide the reference for you -- on the existing submit hook. All you have to do is clone it:

In your hook_form_alter:

<?php
  $form
['#submit']['my_very_own_form_submit'] = current($form['#submit']);
?>

Just put your function name as the key to the array. If you like, add additional arguments using array_merge. ...= array_merge(current($form['#submit']), array($arg1, $arg2, $arg3);

This same approach will also work with #validate, #process, or #after_build callbacks.

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

sym’s picture

Thanks to some help on IRC, I found

<?php
    $form
['#submit'] = array('my_very_own_form_submit' =>
          array()) + (array)
$form['#submit'];
?>

Works

I had some problems when $form['#submit'] didn't exist and current() broke it.

nicholasThompson’s picture

... is that the order that the submit functions get called is the same order that they're in that array - so in Sym's example above, 'my_very_own_form_submit' will get executed BEFORE the origional form's submit hook.

This is often not desirable as you wont know the ID of the submit until you've actually submit and created a node/term/whatever.

wishcow’s picture

I guess you can replace the submit function as well in this method no? by deleting the values in $form['#submit']?

peterpoe’s picture

If the form already has more than one submission function, add your own with:

<?php
$form
['#submit'] = array_merge(array('my_very_own_submit' => array($additional_parameter)), $form['#submit']);
?>
dman’s picture

I found when adding an extra submit handler to a system_settings_form() form, the default handler was not called afterwards.

<?php
/**
 * Admin settings form callback.
 */
function sitesynch_admin_settings() {
 
$form = array();
 
$form['myvariable'] = array(
   
'#type' => 'text',
   
'#default_value' => variable_get('myvariable),
  );
  $form['
mybutton'] = array(
    '
#type' => 'submit',
   
'#value' => 'Do Action',
  );
 
$form['#submit']['sitesynch_admin_settings_submit'] = array();
  return
system_settings_form($form);
}
?>

This caught my button for my custom action OK ... but stopped saving the rest of my settings as usual,
I had to then replace the normal form handler myself.

<?php
 
// Adding my own extra handler makes it forget the default one?
  // That shouldn't happen. Put it back.'
 
$form['#submit']['system_settings_form_submit'] = array();
?>

... I'm aware that current practice is to return just the $form and call system_settings_form at a higher level - this was originally 4.7 code now in 5.3. I dunno if that will make a difference.

.dan.
How to troubleshoot Drupal | http://www.coders.co.nz/

deekayen’s picture

acomer’s picture

If you are going to chain more than one handler, do not use array_reverse as is shown in the example. Calling array_reverse multiple times (as in different hook_form_alter instances) will flip flop the array and the handlers may not get invoked in the order in which you expect. If the original handler called drupal_goto(), then your handler may never get invoked. Instead, to be sure that your handler gets invoked before the original handler in any case, do something like:

$form['#submit'] = array_merge(array('my_very_own_submit' => array()), $form['#submit']);

(D5 example)

Alex Comer
Platinum Code
www.platinumcode.com

1kenthomas’s picture

in D6, node/add, I have:

array_unshift ($form['#submit'], 'my_function_submit');

bigmikestudios’s picture

That worked for me, mostly.

I am trying to add a function to the user_register form, and I'd like to use the newly created uid after it's done. I think by prepending the function as you suggest, it executes before the new user is created. Does anyone have any ideas how I could set this up to execute after?

yasirs’s picture

I am saving same problem. I am trying to add a function to outline_node_form (The form to create outline for Book). I want to execute my function after drupal creates book node type. I created my module and added following code to it but drupal executes my function before inserting book node into databse. All i want it to execute my function after inserting book node to database.
Here is code i am using.

<?php
function mymodule_form_alter(&$form, $form_state, $form_id) {   
  if(
$form_id=="outline_node_form"){
   
$form['#submit'][] = 'mymodule_form_mysubmit';
  }
}

function
mymodule_form_mysubmit($form, &$form_state){
   
/// My code here
}
?>

Drupal executes my function first before inserting book node into database. Can anyone help me on how to make drupal to call my function after inserting book into database? Any help will be really appreciated.

yasirs’s picture

Solved this using hook_nodeapi. Further details can be found at http://api.drupal.org/api/function/hook_nodeapi

hellbrus’s picture

Hi yasirs,

I had the same problem, but I fixed it, my solution is:

$form['buttons']['submit']['#submit'][] = 'your_submit_function';