I have an HTML form:
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:
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.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.
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.
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.
nickf provided the best answer, but it won't work in the special case when you have multiple checkboxes with the same name. Instead (if you're using jQuery), you can use a fake checkbox to toggle the value of a real, hidden input like so:
<input type="checkbox" onclick="$(this).next().val(this.checked?1:0)"/>
<input type="hidden" name="verified[]"/>
<input type="checkbox" onclick="$(this).next().val(this.checked?1:0)"/>
<input type="hidden" name="verified[]"/>
Note that only the hidden checkboxes are named.