Generates a form array for a confirmation form.

Generates a form array for a confirmation form.

This function returns a complete form array for confirming an action. The form contains a confirm button as well as a cancellation link that allows a user to abort the action.

If the submit handler for a form that implements confirm_form() is invoked, the user successfully confirmed the action. You should never directly inspect $_POST to see if an action was confirmed.

Note - if the parameters $question, $description, $yes, or $no could contain any user input (such as node titles or taxonomy terms), it is the responsibility of the code calling confirm_form() to sanitize them first with a function like check_plain() or filter_xss().


Anybody’s picture

Could someone perhaps provide a simple usage example combined with another form? I can't get this working :(

amphioxus’s picture

Here is a code example I made to have a blueprint of a form with a confirmation step. It's probably not ideal, but it works for me. (I didn't know how to get around the session variable to keep my information around until the last step.)


 *  Form with confirmation step

function my_module_form($form, &$form_state) {
  $path = current_path(); // path to return to if "cancel" is pressed

  // create a form with a "confirm" step.
  // Initial form first:
  if( !isset( $form_state['storage']['confirm'] ) ) {

    $form['your-field'] = array(
      '#type' => 'textfield',
      '#title' => t('Enter something here'),
      '#description' => t('Description: You will have a chance to review before submitting.'),
      '#required' => FALSE,
      '#size' => 40,
      '#maxlength' => 40,
      '#attributes' => array(
                         'placeholder' => t('enter whatever here')

    $form['confirm'] = array(
  		'#type' => 'submit',
  		'#value' => 'Submit',
  		'#submit' => array('my_module_form_submit'),

    return $form;
    // The form shown during the confirmation step:
/*     dpm($form_state); // debug: show the form state */
    // some dummy content:
    $content = '<h4>Confirmation dialog</h4>
    <p> This is shown before the final submit step... </p>

    <p> You have entered "' . $form_state['values']['your-field'] . '"! <p>';

    $content .= '<p> But "' . $form_state['values']['your-field'] . '" has not been submitted yet. Click "Really" below to actually submit. </p>';

    $form['intro'] = array('#markup' => $content);

    // create a confirm form:
    // confirm_form($form, $question, $path, $description = NULL, $yes = NULL, $no = NULL, $name = 'confirm');

    return confirm_form($form, $question="Do you really want to make the change?", $path, $description = "Warning, this is the last step before form gets submitted", $yes = "Really?");

  return $form;
} // end of function

// Our submit function
// (Name of the submit function has to be the name of above function + "_submit"!)
function my_module_form_submit($form, &$form_state) {

  if( !isset($form_state['storage']['confirm'] ))
      // not confirmed yet.
      $_SESSION['our_variable'] = $form_state['values']['your-field']; // add our field into a session variable to keep it around for later
      // NOTE: The variable is no longer in $form_state['values']['your-field'] by the time I'm printing out the final confirmation message. I'm
      // not sure session variables are the best solution, but this worked for me.
      $form_state['storage']['confirm'] = TRUE; // this will cause the form to be rebuilt, entering the confirm part of the form
      $form_state['rebuild'] = TRUE;

    // Confirmed: processing of the form happens here:
/*     dpm($form_state); // debug output of $form_state */
    $our_var = $_SESSION['our_variable']; // get back the variable (I don't know how $form_state can be preserved from the earlier stage.)

    drupal_set_message('Now the form got processed and you entered ' . $our_var);


} // end of function
Brian.Harris’s picture

Thanks, your example was great. the only change i would recommend is instead of using session to store the variable, just store the values in the $form_state['storeage'] that way you have all the variables of the first form available.

$form_state['storage']['values'] = $form_state['values'];

Instead of

$_SESSION['our_variable'] = $form_state['values']['your-field']
cafuego’s picture

The example displays user input without sanitising it, creating a XSS scenario. You should run the $form_state['values'] data through the check_plain() function before you output it, use a safe placeholder in the t() function or at least filter_xss() it.

$content .= '

But "' . check_plain($form_state['values']['your-field']) . '" has not been submitted yet. Click "Really" below to actually submit.



$content .= t('

But "@value" has not been submitted yet. Click "Really" below to actually submit.

', array('@value' => $form_state['values']['your-field']));
oadaeh’s picture

In the second example, the <p> tag should not be included in the string that is run through t().

It should be more like this:

$content .= '<p>' . t('But "@value" has not been submitted yet. Click "Really" below to actually submit.', array('@value' => $form_state['values']['your-field'])) . '</p>';
drinkdecaf’s picture

to use the tweak from Brian.Harris, you may also need to include:
$form_state['rebuild'] = TRUE;
in the form submit callback to ensure the form_state is passed back to the form rather than just rebuilt

Maffoo’s picture

Weird bit of code you've got there, doing that whole $yes = "Really?" thing- completely unnecessary and just assigns the string to the variable $yes that then does nothing afterwards. You can remove the assignment entirely from the function call and it would do the same thing.

clancyhood’s picture

See node_menu, node_delete_confirm and node_delete_confirm_submit.

Basically, node_menu adds a path to node/%/delete, which resolves to node_delete_confirm


Sswater Shi’s picture

I use js instead of 'confirm_form', for your reference:

    drupal_add_js('(function($){ $(function(){$("#edit-xxxxxx").click(function(){return confirm("confirm do that ?")});}); })(jQuery);', array('type' => 'inline'));
prabeen.giri’s picture

If you are not validating the CSRF threat on the server side (using drupal token) while deleting any of drupal content using GET method, then you are introducing one using only Javascript confirm on the client side.

For eg,
If some logged in user has permission to delete the node, term, then if other user comments on any page using
<img src='http://admin/structure/term/1/delete'>

Then if logged in user visits that page, then term 1 will get delete without him knowing!!

sri20198’s picture

A simple straight-forward usage example:

 * implements hook_menu()
function example_menu() {
	$items = array();
	$items['example/list'] = array(
		'title' => 'Test list',
		'page callback' => 'example_list',
		'access callback' => TRUE,
	$items['example/%/delete'] = array(
		'title' => 'Delete item',
		'page callback' => 'drupal_get_form',
		'page arguments' => array('example_delete', 1),
		'access callback' => TRUE,
		'type' => MENU_CALLBACK,
	return $items;

function example_list() {
	$header = array('#', 'Item', 'Action');
	$rows = array(
		array(1, 'Apple', l('Delete', 'example/1/delete')),
		array(2, 'Android', l('Delete', 'example/2/delete')),
		array(3, 'Blackberry', l('Delete', 'example/3/delete')),
	return theme('table', array('header' => $header, 'rows' => $rows));

function example_delete($form, &$form_state, $the_id) {
	$form = array();
	$form['the_id'] = array(
		'#type' => 'value',
		'#value' => $the_id,
	return confirm_form(
		t('Are you sure you want to delete this item?'),
		t('This action cannot be undone.'),

	return $form;

 * submit handler for the example_delete
 * this function is invoked only when the user clicks confirm button
 * clickin on cancel, the user goes back to the $path
function example_delete_submit($form, &$form_state) {
	if ($form_state['values']['the_id'] == 1) {
		// do some this here
	drupal_set_message('You confirmed item ' . $form_state['values']['the_id'] . '.');
	$form_state['redirect'] = 'example/list';

erlendstromsvik’s picture

Why do you include the line return $form when it will never be executed?

jonhattan’s picture

In Drupal 8 you want to extend ConfirmFormBase.
Change record: https://www.drupal.org/node/1945416