tags:

views:

379

answers:

3

I have an HTML form:

<form action='process.php' method='post'>
  <input type='checkbox' name='check_box_1' /> Check me!<br>
</form>

Here is a section from the PHP script process.php:

echo (isset($_POST['check_box_1']))?'Set':'Not set';

The output of the script when the checkbox is set is

Set

But when the checkbox is not set, the output is:

Not set

Why is this? This seems like a very poor design because my PHP script checks a number of $_POST variables to make sure they were passed along to the script. When the $_POST['check_box_1'] value is not set, then how do I know whether the script failed to pass along the value or the checkbox was just not set?

+1  A: 

Unfortunately, that's how the spec for checkboxes in submitted forms works - if the checkbox isn't checked, the browser doesn't necessarily send that field at all.

Amber
That's a very poor design idea! Thanks anyway.
George Edison
no, its not. its efficient.
Jayrox
+2  A: 

Only the value of checked checkboxes are submitted to the server. This is an HTML/browser design thing and has nothing to do with PHP. How else do you reliably distinguish a checked checkbox from an unchecked one?

...then how do I know whether the script failed to pass along the value or the checkbox was just not set?

You can trust the browser and PHP to get it right. If it's not set, the box wasn't checked. If you're running some Javascript that submits the form and may get it wrong, it's your responsibility to debug your script.


Regarding "it's bad design":

It's efficient design. There are only two other possibilities, given the limitation that values are send as text only:

  1. Send both the value and the state separately, like checkbox:state=checked&checkbox:value=myvalue. Let's pretend for a second that this would not cause major headaches and ambiguities in what is allowed for input element names and what is not.
  2. Use a magic value to mean "unchecked": checkbox=false. That means I can't make a checkbox like this: <input type="checkbox" name="checkbox" value="false" />

Let's pretend that either solution above would be used and problems associated with them would be solved. That would mean that for every checkbox on the page a POST value would be send. Usually that's not a big deal, but let's imagine a page with 50 checkboxes. Not too unrealistic I'd say. What about one with 200? That's 200 * ~10+ characters extra in HTTP headers for each POST, probably most of them just telling you what the user did not do.

Since this technique was invented when bandwidth was very precious, it's the most efficient to simply not send values of unchecked checkboxes.

deceze
Easy: `check_box_1=true` and `check_box_1=false`
George Edison
The problem is that some nefarious bot roaming the web may request the page - and since it would request the page without the checkbox field set, I would have to treat it just like a legitimate user that submitted the form with the checkbox unset.
George Edison
@George The HTTP protocol that this is sent over only sends text which has no type. How do you distinguish a checkbox with value `"false"` from an unset checkbox?
deceze
@George So...? How can you tell the difference between a bot that didn't check the box and a user that didn't check the box? It's the wrong information to rely on anyway.
deceze
@deceze: You misunderstand me. The actual POST text would be `check_box_1=true` or `check_box_1=false`
George Edison
@George Ditto. :) A checkbox can have *any arbitrary text value*. POST data is only *send as text*. That means you'll have to use some specific **magic text value** which means "not checked", but that means you won't be able to use this value anymore to mean "checked". I.e. you couldn't give your checkbox the value `"false"`, because the text value `"false"` in the POST data means the box is not checked. That would cause a lot more headaches than not sending the value at all to mean "unchecked".
deceze
+4  A: 

If you want to overcome this design feature, try this:

<input type="hidden" name="check_box_1" value="0" />
<input type="checkbox" name="check_box_1" value="1" />

This way, you'll always have $_POST['check_box_1'] set in the callback page, and then you can just check its value to see whether they checked it or not. The two inputs have to be in that order though, since the later one will take precedence.

nickf
Neat idea! Never thought of that.
George Edison