Developer

Handling multiple submits in a single form with PHP

Processing form data in PHP is significantly simpler than most other Web programming languages. This simplicity and ease of use makes it possible to do some fairly complex things with forms, including handling multiple submit buttons in the same form.

Processing form data in PHP is significantly simpler than in most other Web programming languages—a fact you're undoubtedly already aware of if you've been using the language for a while. This simplicity and ease of use makes it possible to do some fairly complex things with forms...including the topic of today's discussion, handling different actions through multiple submit buttons in the same form.

Why multiple submits?

Before I get started, though, let me answer the obvious question: Since most forms are perfectly happy with a single submit button, why would anyone ever need two (or more)?

The best way to explain such a need is with an actual example from the last project I worked on. In that project, I was tasked with building an inventory system for a book-lending library. The book titles were all stored in a database, and administrators could use a browser-based interface to view the record for any book and then perform one of four actions on that record: check out to a member, check in from a member, mark as missing, and mark as sold.

All these activities were handled through a single form, which had buttons corresponding to the actions above. Depending on which button was clicked, the data entered in the form was processed in a different way (check in/out was connected with membership records; mark as missing/sold updated inventory tables). Since a form can only have a single action, the same PHP script had to handle all four tasks, by identifying which button had been clicked and executing the appropriate code branch. Thus, a need arose for a single form carrying multiple submit buttons, and a form-processing script with the intelligence to distinguish between each one.

A single-button form

I'll begin with a simple example—a single form with a single submit button—to ensure you are clear on the basics and to provide a base for the more-complex example. Here is a form:

<html><head>Single-button form</head>
<body>

<form action="processor.php" method="post"> Enter a number: <input type="text" name="number" size="3"> <br>
<input type="submit" name="submit"> </form>

</body>
</html>

And here is the processor.php script that gets invoked on submission:

<?php

// check for submission
// retrieve value from posted data
if ($_POST['submit'])
{
    echo "You entered the number " . $_POST['number']; }

?>

When a form is submitted to a PHP script, PHP automatically creates a special $_POST or $_GET associative array, depending on which method of submission was used (I'll assume POST throughout this tutorial). Values entered into the form input fields are automatically converted to key-value pairs in this array and can then be accessed using regular array notation.

Pay special attention to how the submit button is handled in the above script. When the form is submitted, the submit button itself becomes an element in the $_POST array, with a key corresponding to its "name". This is clearly visible by adding the line:

print_r($_POST);

to the end of the PHP script above. You can look inside the array and clearly see the correspondence between the form controls and their PHP representations.

Now let's take a look at how to handle multi-button forms.

Branching with if/else

Let's now make things a bit more complicated by adding a second submit button to the form:

<html><head>Multi-button form</head>
<body>

<form action="processor.php" method="post"> Enter a number: <input type="text" name="number" size="3"> <br>
<input type="submit" name="add" value="Add 10">
<input type="submit" name="subtract" value="Subtract 10"> </form>

</body>
</html>

Since both submit buttons will invoke the same PHP form processor, that PHP script must be revised to "know" which one was clicked so it can respond appropriately.

Since you already know that the submit button appears in the $_POST PHP array and is keyed by its "name" attribute, it's simple to (1) give each submit button in the form a unique name and (2) write a simple "if" test at the top of the PHP form processor to see which of the two keys appears in the $_POST array and branch the code appropriately. That's exactly what the script below does:

<?php

// check which button was clicked
// perform calculation
if ($_POST['add'])
{
    echo $_POST['number'] . " + 10 = " . ($_POST['number']+10); } else if ($_POST['subtract']) {
    echo $_POST['number'] . " - 10 = " . ($_POST['number']-10); }

?>

If you have a bunch of submits, a good idea is to use a switch/case statement to handle the different code branches more efficiently.

Branching with switch/case

In the previous example, I distinguished between buttons by using different name attributes for the submit buttons in the form. An alternative is giving all the submit buttons the same name, but different values:

<html><head>Multi-button from with switch/case</head>
<body>

<form action="processor.php" method="post"> Enter a number: <input type="text" name="number_1" size="3"> <br> Enter another number: <input type="text" name="number_2" size="3"> <br>
<input type="submit" name="calculate" value="add">
<input type="submit" name="calculate" value="subtract">
<input type="submit" name="calculate" value="multiply"> </form>

</body>
</html>

The processing script needs to check the value of the $_POST['calculate'] element, and branch the code appropriately. The most efficient way to do this is with a switch-case statement, as follows:

<?php

// branch on the basis of 'calculate' value
switch ($_POST['calculate']) {
      // if calculate => add
      case 'add':
            echo $_POST['number_1'] . " + " . $_POST['number_2'] . " = " . ($_POST['number_1']+$_POST['number_2']);
            break;

      // if calculate => subtract
      case 'subtract':
            echo $_POST['number_1'] . " - " . $_POST['number_2'] . " = " . ($_POST['number_1']-$_POST['number_2']);
            break;

      // if calculate => multiply
      case 'multiply':
            echo $_POST['number_1'] . " x " . $_POST['number_2'] . " = " . ($_POST['number_1']*$_POST['number_2']);
            break;
}

?>

Depending on which button gets clicked, the appropriate value is passed to the processing script and the corresponding "case" block is invoked. If you have a large number of submit buttons to deal with, this approach is easier to read and understand than multiple if-else blocks.

But what about the case where you've got graphical submit buttons instead of text-based?

Using graphical submit buttons

A minor twist in the tale comes if you use a graphical submit button, as in the following simple form:

<html><head>Graphical submit button</head>
<body>

<form action="processor.php" method="post"> Search for: <input type="text" name="q">
<input type="image" name="go" src="/images/go.gif"> </form>

</body>
</html>

When this form is sent to PHP for processing, look what the $_POST array contains:

Array
(
    [q] => magpie
    [go_x] => 13
    [go_y] => 13
)

Because it's a graphical button, PHP actually tracks the mouse coordinates of the mouse click and creates two elements in the result array to store those coordinates. The elements are named [button_name]_x and [button_name]_y respectively.

Why is this important? Well if you'd been using an if() test keyed on the submit control's "name" the test would have failed because instead of creating a single element accessible through $_POST['go'], PHP actually created two elements named $_POST['go_x'] and $_POST['go_y'] respectively. Make a mental note of this for future reference; it might save you some time when things don't work as expected.

So now, what happens if you have multiple graphical submit buttons in your form:

<html><head>Multiple graphical submit buttons</head>

<body>

<form action="processor.php" method="post"> Enter part number: <input type="text" name="part"> <br>
<input type="image" name="view" src="/images/view.gif">
<input type="image" name="edit" src="/images/edit.gif">
<input type="image" name="delete" src="/images/delete.gif">
<input type="image" name="order" src="/images/order.gif"> </form>

</body>
</html>

Your PHP script would need to contain multiple branches, something like this:

<?php

if ($_POST['view_x']) {
      // code to view record
} else if ($_POST['edit_x']) {
      // code to edit record
} else if ($_POST['delete_x']) {
      // code to delete record
} else if ($_POST['order_x']) {
      // code to place an order
}

?>

Finally, here's a real-life example to tie it all up. This example consists of a dynamically-generated form with a list of e-mail addresses from a user's address book. The user can select one or more addresses from this list and then add them to a whitelist or a blacklist; (s)he can also remove them from the address book. The form contains three action buttons corresponding to these three tasks. Take a look at Listing A.

Notice that, in this case, the submit buttons are named like PHP array elements, with the key representing the action. When the form is submitted, this naming scheme will cause a single-element array to be created within the $_POST array; this can then be used to identify the action and execute the appropriate code branch using a switch-case statement, as you can see in Listing B.

Editor's Picks