How come checkbox state is not always passed along to PHP script?
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
But when the checkbox is not set, the output is:
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?
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.
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?
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:
- 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.
- 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.
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.
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.