Create an action confirm form using “confirm_form()” function in Drupal

Doctor's List with delete option

Doctor's List with delete option

Action confirm form in Drupal

Action confirm form in Drupal

We can easily create an action confirm form using confirm_form() function in Drupal. Normally we need this form when user want to delete something and we want user to confirm his/her action. I am showing here an example in which we are listing all the Doctors information with Edit and Delete option. When user click the delete link we will show him the action confirm form with “Delete” and “Cancel” options. If user click the “Delete” button we will delete that Doctor record from database and if user click on “Cancel” we simply show the doctors list again.

Here is the code. I am using the module name “doctor” in this example.

Step 1. First implement hook_menu() to register new path in Drupal.

function doctor_menu() {
  $items = array();
  $items['doctors'] = array(
    'title' => t('Doctors'),
    'page callback' => 'doctors_list',
    'access arguments' => array('access doctor'),
    'type' => MENU_CALLBACK,
  $items['doctors/delete/%doctor_user'] = array(
    'title' => t('Delete doctor'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('doctor_delete_confirm', 2),
    'access arguments' => array('access doctor'),
    'type' => MENU_CALLBACK,
  return $items;

Step 2. Implementing the doctors_list() function to display the list of doctors.

function doctors_list() {
	$header = array(t('Doctor Name'), t('Gender'), t('Phone No.'), t('Status'), t('Action'));
	$query = "SELECT * FROM {doctor}";
	$rs = db_query($query);
	$row = array();
	if ($rs) {
		while ($data = db_fetch_object($rs)) {
			$gender = $data->gender == 'M' ? t('Male') : t('Female');
			$status = $doctor->status ? t('active') : t('inactive');
			$row[] = array(stripslashes($data->firstname) . ' ' . stripslashes($data->lastname), $gender, stripslashes($data->phoneno), $status, 
			"<a href='/doctors/edit/{$data->doctorid}'>" . t('Edit') . "</a> | <a href='/doctors/delete/{$data->doctorid}'>" . t('Delete') . "</a>");
	$str .= theme_table($header, $row);
	return $str;

Step 3. Create a wildcard loader function doctor_user_load() which we used in “doctors/delete/%doctor_user” path. This function checks the given “ID” in path is valid or not. If the given doctor id is not exists in database then “Page not found.” message will display.

function doctor_user_load($doctorid) {
	$query = "SELECT * FROM {doctor} WHERE doctorid = %d";
	$rs = db_query($query, $doctorid);
	if ($rs) {
		while ($data = db_fetch_object($rs)) {
			return $data;
	return FALSE;

Step 4. Create the doctor_delete_confirm() function. We are using the “confirm_form()” function in this function to show action confirm form.

function doctor_delete_confirm(&$form_state, $doctor) {
	$form['_doctor'] = array(
		'#type' => 'value',
		'#value' => $doctor,
	return confirm_form($form,
    	t('Are you sure you want to delete this doctor?'),
    	isset($_GET['destination']) ? $_GET['destination'] : "doctors",
    	t('This action cannot be undone.'),

Step 5. Create the Form API submit function for doctor_delete_confirm form.

function doctor_delete_confirm_submit($form, &$form_state) {
	$form_values = $form_state['values'];
	if ($form_state['values']['confirm']) {
		$doctor = $form_state['values']['_doctor'];
		doctor_delete($form_state['values'], $doctor->doctorid);			
		drupal_set_message(t('Doctor has been deleted successfully.'));

, ,

  1. #1 by Mark - September 1st, 2009 at 02:13

    I’m looking through your code for this example and have a few questions I hope you won’t mind helping me with.

    In Step 1, what is “%doctor_user” a reference to? In Step 3 the description says the function is based on the reference to the path for the doctor/delete in Step 1, but I don’t understand how it relates to “$doctorid” and “doctorid” in Step 3.

    In Step 4, in the line of code “isset($_GET[‘destination’]) ? $_GET[‘destination’]”, what is ‘destination’ a reference to?

    Thanks again for the examples.

  2. #2 by admin - September 1st, 2009 at 08:10

    @ Mark
    I always love to reply on users comments. So, here is my comments on your questions.

    In Step 1, what is “%doctor_user” a reference to?
    Reply – ““%doctor_user” is a wild card loader function. This is very important concept of Drupal menu system and available in Drupal Version 6.
    When you open path “/doctors/delete/6″ in your browser, Here “6” is the doctor’s user id. Drupal pass this user id to “doctor_user_load($doctorid)” function. Here important thing is Drupal itself add “_load” at the end of wild card loader function. If the doctor with this user id exists then this function return doctors object with his/her complete detail. If this doctor user id is invalid/incorrect then Drupal show the “Page not found” message.

    In Step 3 the description says the function is based on the reference to the path for the doctor/delete in Step 1, but I don’t understand how it relates to “$doctorid” and “doctorid” in Step 3.

    Reply – In menu hook “doctor_menu()”, I’ve used line
    ‘page arguments’ => array(‘doctor_delete_confirm’, 2),
    It’s means, when you access “doctors/delete/6″ path in browser Drupal first call the wild card loader function as explained above. After that Drupal call “doctor_delete_confirm()” function and pass argument 2 to this function. Here argument “2” is doctor information object which is returned by “doctor_user_load()” function not the doctor id (“6″) which is available in path.

    In Step 4, in the line of code “isset($_GET[‘destination’]) ? $_GET[‘destination’]“, what is ‘destination’ a reference to?
    Reply – In Drupal, you can specify the destination for any form. It means when we submit a form we can specify where should we redirect user after submitting form by giving “destination” in URL as query string. Like this:-
    URL – /doctors/delete/6?destination=/doctors/list
    So, after submission the Drupal will redirect user to “/doctors/list” location.
    So, in line ‘isset($_GET[‘destination’]) ? $_GET[‘destination’] : “doctors”,’, I’m checking if destination is available in query string then use it, otherwise redirect user to “/doctors” location after deleting doctor record.

    Hope this explanation is helpful.

  3. #3 by Mark - September 1st, 2009 at 17:47

    Thanks, that helps a lot. I have another question, and may have more once I have time to really work on this example again.

    In step 3, are $doctorid and doctorid equivalent values?

  4. #4 by Mark - September 1st, 2009 at 18:14

    Cheers again, I just noticed in your reply you mentioned Drupal 6. Will the loader call work in Drupal 5 as well (which is what my client is using)?

  5. #5 by John - September 28th, 2009 at 23:02

    How do you have the confirm form appearing below the list of doctors? My confirm form page reloads into a new page.

  6. #6 by andy - October 30th, 2009 at 23:24

    Thanks man,
    It was really helpful for me. I have a question, what does
    drupal_get_form contains ? are you going to retrieve the doctor details along with delete and confirm buttons in this page or any thing else..

  7. #7 by admin - October 31st, 2009 at 10:05

    drupal_get_form takes the form_id and process it and return the rendered form for display. Here we are passing ‘doctor_delete_confirm’ form in drupal_get_form. You can investigate more about it here

    Yes, we are retrieving the doctor details with delete and confirm button with the help of ‘%doctor_user’. doctor_user_load is a wild card load function and take the 3rd parameter from URL (in this case doctor_id). Then we pass the ‘$doctor’ object with complete doctor detail into doctor_delete_confirm function. When user confirm his/her action we retrieve the doctor_id from this object and delete the doctor detail from database. Hope this reply is helpful.

  8. #8 by andy - November 6th, 2009 at 20:16

    Thanks man,
    It’s working fine…thanks for u’r help…

  9. #9 by secure - November 11th, 2009 at 07:57

    Thaks nice tutorial and good answer .
    it’s work and i’m also understand.

  10. #10 by Matthew Slater - December 16th, 2009 at 14:47

    Thanks for this clear tutorial, there’s not much to be found on this subject. My question is, how do you get to confirm_form from a previous form submission, rather than from a link?
    I have a complex form which I want to summarise on the confirmation page, and I don’t want to pass all the form fields using callback arguments.

  11. #11 by admin - December 16th, 2009 at 16:48

    @ Matthew Slater
    Hi Matthew,

    I understand your question. I’m not sure we can achieve your requirement through confirm_form. But you can try Drupal Multi-step forms. You can create first step form for input and second step form for confirmation. Some useful links.

    1. (Code sample #10)

    You can also Google for more information.

  12. #12 by Matthew Slater - December 16th, 2009 at 19:09

    @ admin
    Thanks. Multistep isn’t working well for me, the code is too deep. But I guess I shall have to choose between them.

  13. #13 by Jaime Navarro - February 5th, 2010 at 17:28

    Thanks, great tutorial!

    I tried to test it in my page but I did not succeed.

    I try to explain the best i can, my english is bad.

    I work in a web page of dentinsts profiles (CCK content type with a lot of fields), I need to show a button at the edit form which set the status of node to 0. But I want to show a confirm form before. I do not get it to work with a button submit.

    Thank you.

  14. #14 by Ajay - July 28th, 2010 at 13:07

    Thanks for a great tutorial, your example in step 2 lists records by “$str .= theme_table($header, $row);
    1. Now if we simply add “$str .= theme(‘pager’, NULL, $limit, 0);”, we’ll get a paginated listing.

    2. With this paginated listing how can we add check boxes (array) with all the records and a delete button on top/bottom of listing to perform a bulk delete operation?


  15. #15 by luv - July 2nd, 2012 at 16:22

    this is thankful for me

    regards & thanks again

  16. #16 by bala - March 9th, 2013 at 15:57

    Hi , i gone through this example, i seems good for creating the custom module , but i have one doubt in the can you please explain the line doctor_delete(); because i used same , but i am getting an fatal error
    can you please explain what does it mean?

  17. #17 by Luciano - April 26th, 2013 at 23:41

    whoah! excellent!

    I’m refactoring my recently-released module, which used to rely solely on variable_get().

    it now uses tables, so I’m building the whole CRUD for it.

    your tutorial was very helpful; thanks a lot!

    please check out my module if you like:

Comments are closed.