7.x form.inc drupal_form_submit($form_id, &$form_state)

Retrieves, populates, and processes a form.

This function allows you to supply values for form elements and submit a form for processing. Compare to drupal_get_form(), which also builds and processes a form, but does not allow you to supply values.

There is no return value, but you can check to see if there are errors by calling form_get_errors().

// register a new user
$form_state = array();
$form_state['values']['name'] = 'robo-user';
$form_state['values']['mail'] = 'robouser@example.com';
$form_state['values']['pass']['pass1'] = 'password';
$form_state['values']['pass']['pass2'] = 'password';
$form_state['values']['op'] = t('Create new account');
drupal_form_submit('user_register_form', $form_state);


$form_id: The unique string identifying the desired form. If a function with that name exists, it is called to build the form array. Modules that need to generate the same form (or very similar forms) using different $form_ids can implement hook_forms(), which maps different $form_id values to the proper form constructor function. Examples may be found in node_forms() and search_forms().

$form_state: A keyed array containing the current state of the form. Most important is the $form_state['values'] collection, a tree of data used to simulate the incoming $_POST information from a user's form submission. If a key is not filled in $form_state['values'], then the default value of the respective element is used. To submit an unchecked checkbox or other control that browsers submit by not having a $_POST entry, include the key, but set the value to NULL.

...: Any additional arguments are passed on to the functions called by drupal_form_submit(), including the unique form constructor function. For example, the node_edit form requires that a node object be passed in here when it is called. Arguments that need to be passed by reference should not be included here, but rather placed directly in the $form_state build info array so that the reference can be preserved. For example, a form builder function with the following signature:

function mymodule_form($form, &$form_state, &$object) {

would be called via drupal_form_submit() as follows:

$form_state['values'] = $my_form_values;
$form_state['build_info']['args'] = array(
drupal_form_submit('mymodule_form', $form_state);

For example:

Related topics

4 calls to drupal_form_submit()
aggregator_form_opml_submit in modules/aggregator/aggregator.admin.inc
Form submission handler for aggregator_form_opml().
batch_test_programmatic in modules/simpletest/tests/batch_test.module
Menu callback: programmatically submits the 'Chained' form.
FormsProgrammaticTestCase::submitForm in modules/simpletest/tests/form.test
Helper function used to programmatically submit the form defined in form_test.module with the given values.
_batch_test_nested_drupal_form_submit_callback in modules/simpletest/tests/batch_test.module
Batch operation: submits form_test_mock_form using drupal_form_submit().


includes/form.inc, line 723
Functions for form and batch generation and processing.


function drupal_form_submit($form_id, &$form_state) {
  if (!isset($form_state['build_info']['args'])) {
    $args = func_get_args();
    $form_state['build_info']['args'] = $args;

  // Merge in default values.
  $form_state += form_state_defaults();

  // Populate $form_state['input'] with the submitted values before retrieving
  // the form, to be consistent with what drupal_build_form() does for
  // non-programmatic submissions (form builder functions may expect it to be
  // there).
  $form_state['input'] = $form_state['values'];
  $form_state['programmed'] = TRUE;
  $form = drupal_retrieve_form($form_id, $form_state);

  // Programmed forms are always submitted.
  $form_state['submitted'] = TRUE;

  // Reset form validation.
  $form_state['must_validate'] = TRUE;
  drupal_prepare_form($form_id, $form, $form_state);
  drupal_process_form($form_id, $form, $form_state);


jhodgdon’s picture

In Drupal 6, this function was called:

devoted.designer’s picture

Needing a "Create a new node" example, like in the Drupal 6 drupal_execute() documentation.

Could you please post one?!

cedwards.rei’s picture

adham121’s picture

I use this code to create a new node . but the big problem is that I can't insert data into a custom field ??!! Can anybody help

define('DRUPAL_ROOT', getcwd());

include_once DRUPAL_ROOT . '/includes/bootstrap.inc';

ini_set('memory_limit', '512M');

//Authenticate as user 1
user_authenticate('user', 'password');

module_load_include('inc', 'node', 'node.pages');  // new for Drupal 6

   $form_state = array();
   $nodeTmp = array('type' => testimonial); // a variable holding the content type

   $form_state['values']['type'] = 'testimonial';
   $form_state['values']['status'] = 1;
   $form_state['values']['title'] = 'test1';   // the node's title
   $form_state['values']['body'] = 'just my test node'; // the body, not required
   $form_state['values']['field_name'] =  t('adham allam');
   $form_state['values']['status'] = 1; //publish all imported nodes
   $form_state['values']['promote'] = 1; //promote all imported nodes
   $form_state['values']['sticky'] = 0; //remove sticky from imported nodes
   $form_state['values']['image'] = array();
   $form_state['values']['name'] = 'adham';
   $form_state['values']['op'] = t('Save');  // this seems to be a required value

drupal_form_submit('testimonial_node_form', $form_state, (object)$nodeTmp);
jpwarren00’s picture

Same as above but you need to copy the $form_state values from the specific node content type with the custom field you want to populate.

$form_state['values']['field_legacy_reference_id'] = array(
  'und' => array(
      'value' => $key,

You can get that data structure with hook_node submit in a little 3 line module.

function your_module_name_node_submit($node, $form, &$form_state) {

Then manually create a piece of content and you'll get the full data structure for that content type, custom fields and all.

artfulrobot’s picture

e.g. you have the file, and need to tell drupal it's part of a new node you're creating.

Seen exampled for Drupal 6, but not 7.

Hammad.Chishti’s picture

Couldn't find in drupal 7, got some hint but still not successfull:(

$filename = 'test.jpg';
$image = file_get_contents('http://test.com/images/M/MV5BNjkyOTI5MDA0Ml5BMl5BanBnXkFtZTcwOTU3NzExNw@@._V1._SY0.jpg');
$file = file_save_data($image, 'public://images/poster/' . $filename, FILE_EXISTS_REPLACE);
$temp = $file->fid.$i;

$form_state['values']['field_poster']['und'] = array( 'fid'=>$temp, 'filename'=>$file->filename, 'uri'=>$file->uri, 'filemime'=>$file->filemime, 'filesize'=>$file->filesize, 'display' => '1',
'width' => '743',
'height' => '1100');

Hyp1’s picture

a file field can yield multiple files and is always an array:

so i guess your code should be like:
$form_state['values']['field_poster']['und'][] = array( 'fid'=>$temp, 'filename'=>$file->filename, 'uri'=>$file->uri, 'filemime'=>$file->filemime, 'filesize'=>$file->filesize, 'display' => '1',
'width' => '743',
'height' => '1100');

gianfrasoft’s picture

Needing a "webform submit" example.

wolffereast’s picture

I realize this is old, but it popped up in my search when looking for an answer. Hope this helps someone else!

$webform_node_id = [num];

if ($node = node_load($webform_node_id)){
  $form_state = array(
    'values' => array(
      [value_1_machine_name] => [value_1],
      [value_2_machine_name] => [value_2],
      'op' => t('Submit'),

  //need to set the submitted key in the values, as this is required by webform
  $form_state['values']['submitted'] = $form_state['values'];

  drupal_form_submit('webform_client_form_'. $webform_node_id, $form_state, $node, array());
  if (form_get_errors() != '') {
    print 'Webform_Error';
    print '
'.print_r(form_get_errors(), 1).'

else print 'Webform_Success';

You can grab the value machine names from the Field Key field when editing form components.
Be sure to check the 'op' variable, as my submission did not succeed without this item
If you do not set a value for a required component you will receive an error explaining this.

This code was used in a custom php script to submit a webform.

ellenoise’s picture

Thanks for the detailed example, wolffereast!

I recently built a custom form that submits to a separate Webform. Webform kept throwing this error: Submissions for this form are closed. My webform's status was open, so the error was pretty misleading. Come to find out, my input wasn't passing this webform function: webform_input_vars_check(). To force my array to pass Webform's checks, I needed to provide a value for 'form_id'.

Looks pretty similar to wolffereast's solution:

* My custom form's submit handler.
function mymodule_form_submit($form, &$form_state) {
  $webform_node_id = [num];
  $node = node_load($webform_node_id);

  $form_input = array(
      [value_1_machine_name] => [value_1],
      [value_2_machine_name] => [value_2],
      'op' => t('Submit'),
  $new_form_state['values'] = $form_input;
  $new_form_state['values']['submitted'] = $form_input;

  // Needed to force input to pass webform_input_vars_check():
  $new_form_state['values']['form_id'] = 'webform_client_form_' . $webform_node_id;

  drupal_form_submit('webform_client_form_' . $webform_node_id, $new_form_state, $node, array());

hash6’s picture

Can node_save() be used in place of drupal_form_submit() ?

jmcejuela’s picture

node_save is somewhat easier to use, but drupal_form_submit (which in the end also calls node_save through node_form_submit) additionally fires up the form hooks, which other modules can listen to and react upon. So by using drupal_form_submit your module is more flexible and can better interact with other modules.

ezman’s picture

I have a custom module which creates a multi-step user registration form, and am trying to display the validation errors in a more user-friendly way (ie. not lumped together in the error messages output).
I can't get form_get_errors() to return anything, no matter where I put it in my custom module.
I first tried calling it in my _form_alter hook, then in my _submit callback, I then saw (here: http://drupal.stackexchange.com/questions/28355/hook-form-alter-isnt-bei... ) a suggestion to user #after_build, so I've added an #after_build callback function "mi_register_check_errors":

function mi_register_check_errors($element) {
	$errors = form_get_errors();
	if ( $errors ) {
	} else {
		drupal_set_message("errors = false");

	$elemerror = form_get_error($element);
	if ( $elemerror ) {
	} else {
		drupal_set_message("elemerror = false");
	return $element;

Now if I load the form, submit it and get validation errors (form reloads with fields given error class), or submit it correctly; the only thing I ever get is that there's no error.

Any ideas how I can get form_get_errors to actually return something if there's an error?
(I'm using #limit_validation on my multi-step form so that only the submitted fields are validated when the user clicks the 'next' button)

ezman’s picture

It seems form_get_errors() returns false in most places. I think the errors are processed and then cleared so they're not accessible at the point I was checking them.

The solution is to check the errors in a validate callback:
In my MYMODULE_register_form_user_register_form_alter() function:
$form['#validate'][] = 'MYMODULE_register_register_validate';

And then the validate handler:

 * Validate handler.
function MYMODULE_register_register_validate(&$form, &$form_state) {
//validate does not actually validate -just prefixes error messages to fields that have errors:
	$errors = form_get_errors();
	if ( $errors ) {
		foreach ( $errors as $name=>$value ) {
			if ( isset( $form['account'][$name] ) ) {
				$form['account'][$name]['#prefix'] = '
' . $value . '
'; } } } }
nikolaosinlight’s picture

We have a form search form with basic criteria (name, id, etc...) and a submit button with say URL /search/invites/<id> where IFF <id> is passed in we would like to set the criteria to the value of <id> and automatically submit the form.

I tried drupal_submit_form HOWEVER to my dismay it does not return the resulting form. So I cloned the method and modified it to have it simply return the form however on any subsequent form submit I get that the form is outdate and needs to be reloaded.

While I see the benefit of programmatic form submit WITHOUT form results HOW does one go about doing programmatic form submit **WITH** corresponding form results?

I find I am going to all sorts of crazy lengths just to get something so simple to work... there MUST be an easier solution that I am simply missing.

jkoenig’s picture

After updating with this security patch, I can't retrieve my URL parameter from the query string. I attempted using arg() and nothing there either. The system appears to be preventing access .. is this the case? If so what is the work around. I have data the is pulled into the node from another database - the URL parameter defines the data lookup.

golds’s picture

function add_images_to_node_form($images, $field, $instance) {
    $values = array();
    $values[LANGUAGE_NONE] = array(
      "array_parents" => array(),
      "errors" => array(),
      "field" => $field,
      "instance" => $instance,
      "items_count" => 1
    if (empty($images)) {
      $values[LANGUAGE_NONE]['items'][0] = array("_weight" => 0,
        "fid" => 0, 
        "display" => 1, 
        "description" => "",
        "upload_button" => "Upload", 
        "remove_button" => "Remove", 
        "upload" =>  "",
        "alt" => "",
        "title" => "");  
      return $values;
     // add images to form state
    $values[LANGUAGE_NONE]['items'] = array();
    if (!is_array($images)) {
      $images = array($images);
    foreach ($images as $path) {
      $length = strrpos($path, '/');
      $filename = substr($path,  $length+1);
      $fid = db_query("select fid from file_managed where filename='" . $filename . "'")->fetchField();
      $file = file_load($fid); 
      $values[LANGUAGE_NONE]['items'][] = (array)$file;
    $values[LANGUAGE_NONE]['items_count'] = count($images);
    return $values;

Call to function:

$field = field_info_field("field_images");
$instance = field_info_instance("node", "field_images", "content_type_name");
$form_state['field']['field_images'] = add_images_to_node_form(array("http://example.com/sites/default/files/dd.png", "http://example.com/sites/default/files/kk.png"), $field, $instance);
bbu23’s picture

does anybody know how to programmatically submit a drupal form that has the #action set to external URL ? For me, it`s not working

BarisW’s picture

If you want to replace the Title field from a node with a 'Title' Field API field (using the Title module), you can use the following update hook.

 * Replaces the title field on News nodes.
function MYMODULE_update_X() {
  module_load_include('inc', 'title', 'title.admin');
  $form_state['values']['enabled'] = 1;
  drupal_form_submit('title_field_replacement_form', $form_state, 'node', 'news', 'title');
  if (form_get_errors()) {
    throw new DrupalUpdateException('Could not replace the title field.');
artisingh’s picture

I'm using the drupal 7 and when I call this function to submit a form I got the following error: EntityMalformedException: Missing bundle property on entity of type node. in entity_extract_ids() (line 7818 of /var/www/html/clientela-liujo/includes/common.inc).

$form_state = array(
'values' => array(
'type' => 'email_schedule',
'uid' => $user->uid,
'created' => time(),
'language' => und,
'name' => $user->name,
'status' => 1,
'promote' => 0,
'sticky' => 0,
'submit' => 'Send',
'preview' => 'Preview',
'field_email_template' => array(und => array(array('target_id'=> $temp_node->nid))),
'field_sailthru_job_id' => array(und => array(array('value'=> ''))),
'field_sailthru_job_name' => array(und => array(array('value'=> ''))),
'field_sailthru_job_status' => array(und => array(array('value'=> ''))),
'field_sailthru_list' => array(und => array(array('value'=> ''))),
'field_schedule_date' => array(und => array(array('value'=> time(), 'value2' => '', 'timezone'=> '', 'offset' => '', 'offset2' => '', 'rrule' => ''))),
'field_schedule_recipients' => array(und => array($recipient_uid => array('target_id'=> $recipient_uid))),
'field_list_reference' => array(und => array(array('target_id'=> ''))),
'field_name_reference' => array(und => array(array('target_id'=> ''))),
'field_category' => array(und => array(array('tid'=> ''))),
'title' => time(),
'op' => t('Submit'),
drupal_form_submit('email_schedule_node_form', $form_state);

can anybody help me what's the issue with this code?