Forum Moderators: coopster

Message Too Old, No Replies

unchecked checkboxes - fields with the same name

         

millyre

12:41 pm on Feb 16, 2006 (gmt 0)

10+ Year Member



Hi all.

I'm trying to set up a web form to catch unchecked checkboxes. The problem is of course that the value only is passed to the server when the checkbox is set.

I've seen various javascript solutions (setting a hidden field onclick()), but I've tried a different solution, which seems to work:

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

If the checkbox is checked, the value of c01 will be "1", otherwise the value of the hidden field will be passed to the server.

Any comments on this solution? Does it depend on how the browser treats multiple elements with the same name, or are all browser required to handle these the same way according to the spec (ie pass the last or both values in the POST/GET string, to pass them in the same order?)

On the server side, can one expect apache/php to handle the data in a predictable manner? Is it possible that when handling multiple fields with the same name, that an arbitrary field will be preserved, or will always the last one end up in $_POST/GET? Is it possible that the data will be represented in ie an array() in different implementations/versions/servers?

Any thoughts/recommendations?

Thanks!

Scally_Ally

3:25 pm on Feb 16, 2006 (gmt 0)

10+ Year Member



I would imagine that you have to have the hidden field and the checkbox names different to each other as one would over-ride the other (i think..).

Could you do something like this

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

and then use the isset() to determine whether it has been checked
<?
if(isset($_POST["c01"]) == false ¦¦ $_POST["c01"] == ""){
$value = $_POST["B01"];
}
?>

coopster

5:43 pm on Feb 16, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Welcome to WebmasterWorld, millyre.

I would not name them the same. Since you already know what the checkboxes values could possibly be on the server-side, why not just check what was passed back from the form against those values again? Load them up in an array first.

millyre

9:42 am on Feb 17, 2006 (gmt 0)

10+ Year Member



Hi, thank you both for your responses!

Your suggestions are probably the best and most common way to solve the 'problem'. I'm currently using a hidden field with another name (solution #1).

However, it would be interesting to know what the 'specs' say, if anything, on the issue of multiple (different) input fields with the same name. How is the browser and/or server supposed to treat these? I seem to recall that IIS is different that apache/php in this regard.

tomda

9:55 am on Feb 17, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi Millyre,

I would follow Coopster's advice that is load all the checked value in an array and work with the two arrays.

coopster

11:00 pm on Feb 17, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member




However, it would be interesting to know what the 'specs' say, if anything, on the issue of multiple (different) input fields with the same name. How is the browser and/or server supposed to treat these? I seem to recall that IIS is different that apache/php in this regard.

Assuming you are talking about the HTML 4.01 specs -- several fields may share the same name, as a matter of fact, that is often how checkboxes and radio buttons are used. Each successful control [w3.org] is "valid" for submission. It's not Apache or IIS that treats this differently but the server-side scripting language you are using.

I realize this isn't a perl discussion, but I'll just add that perl puts like names in to an array automagically if you are using the cgi.pm module. Perl reads from STDIN and you write your own parser, unless you are using something like the module mentioned.

PHP will automatically put anything named with braces ([]) into an array for you. But if you have more than one form variable without those braces, you are going to get unexpected results -- a single value as opposed to an array of the multiple values in the $_GET/$_POST superglobals. However, you can always have a look at what is being pushed back if you read the raw HTTP POST data. There are a couple of ways to do this, but

$RAW_POST_DATA = file_get_contents("php://input");

is the least memory intensive when you want to read from the PHP input stream [php.net]. Those familiar with the old $HTTP_RAW_POST_DATA array will notice these are the same thing, the difference being the suggested method is less memory intensive and does not need any special php.ini directives (to populate the $HTTP_RAW_POST_DATA superglobal you have to set the
always_populate_raw_post_data
configuration directive in php.ini, .htaccess or httpd.conf as it is of type
PHP_INI_PERDIR
):

php_flag always_populate_raw_post_data On

This may be confusing as it is a bit more advanced, but if anybody wants an example just let me know and I'll post a demonstration here ...

millyre

10:05 am on Feb 20, 2006 (gmt 0)

10+ Year Member



Thanks coopster!

Does 'unexpected results' mean that it is not possible to know which of the values will end up in the superglobals, or that the results will be 'flattened' (as compared to cgi.pm), and that the latest value always will replace any preceding in GET/POST?

coopster

2:59 pm on Feb 20, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



I don't have time to pull the source code to find out but I would guess the latter. Here is a quick demonstration that proves the theory but I cannot confirm that it will always be the last value that would be stored in the same-name variable -- like I said, you would have to pull the PHP source code to truly verify.
<html><head><title>Test</title></head><body> 
<?php
if (isset($_POST['Submit'])) {
print '<pre>';
readfile("php://input");
print "\n\n";
print_r($_POST);
print '</pre>';
}
?>
<form action="<?php print strip_tags($_SERVER['REQUEST_URI']);?>" method="post">
<fieldset>
<legend>Test</legend>
<input name="text01" type="text" value="hello" /><br />
<input name="text01" type="text" value="hello again" /><br />
<!-- uncomment the next line and you will see that PHP replaces
the previous name=value pair in the $_POST array index with
the last value read in: -->
<!-- <input name="text01" type="text" value="hello again, again!" /><br /> -->
<input name="Submit" type="submit" value="Submit" />
</fieldset>
</form>
</body>
</html>