tags:

views:

85

answers:

4

I am going nuts here, I have an array of checkboxes from a form that I am trying to $_POST with PHP. EVERYTHING on my form posts fine except the check boxes. The checkboxes DO post, but in the wrong order. For instance when I want checkbox[0] and checkbox[2] I actually get checkbox[0] and checkbox[1].

I have tried many different ways to get the value of the checkbox, including isset but I still have the same problem. I just need the checkbox value of on to be stored in my database if the checkbox is indeed checked.

My code is below. $in_production is the checkbox. I can provide the code that generates the checkbox too if it is needed.

Thanks in advance.

if ($_GET['action'] == 'Edit_Product'){

    include("../dbinfo.php");

    $q_id = $_GET['q_id'];

    for ($i = 0; $i < count($_POST['p_id']); $i++){

        $result = mysql_query('SELECT * FROM products WHERE q_id = '.$q_id);
        $num = mysql_num_rows($result);

        $p_id = ($_POST['p_id'][$i]);
        $in_production = ($_POST['in_production'][$i]);
        $p_name = ($_POST['p_name'][$i]);
        $p_price = ($_POST['p_price'][$i]);

        $p_name_conflict = FALSE;

        for ($ii = 0; $ii < $num; $ii++){
            $row = mysql_fetch_array($result);
            $p_name_conflict_check = $row['p_name'];
            $p_id_conflict_check = $row['p_id'];

            if($p_name_conflict_check == $p_name &&
              $p_id_conflict_check != $p_id){
                $p_name_conflict = TRUE;
            }

        }

        if ($p_name_conflict == FALSE){
            $query = "UPDATE products SET p_name='$p_name',
              p_price='$p_price', in_production='$in_production',
              last_modified=CURDATE() WHERE p_id = '$p_id'";
            mysql_query($query);
        }

        else{
            $update_failures =+1;
        }

    }

    mysql_close($link);

    if($update_failures == 0){
        header("Location: Products_Updated.html");
    }

    elseif ($update_failures != 0){
        header("Location: Products_Exist.php?update_failures=".$update_failures);
    }

}

P.S. I don't know why but the code block icons are not present on SO right now... so my code is not all pretty. Also, I know my code is horribly inefficient, but I am just trying to get this working right now, then fine tune later. I am open to efficiency suggestions as well, but that is not my primary objective with this question.

EDIT: Here is the form from the HTML...

        <form id="form" name="form" method="post" action="/Management/Products/Product_Management.php?action=Edit_Product&q_id=<?php echo "$q_id" ?>">

                <?php

                    include("../dbinfo.php");   

                    $result = mysql_query('SELECT * FROM products WHERE q_id =' . $q_id);
                    $num = mysql_num_rows($result);
                    mysql_close($link);

                    for ($i = 0; $i < $num; $i++){
                        $row = mysql_fetch_array($result);

                        $p_id = $row['p_id'];
                        $p_name = $row['p_name'];               
                        $p_price = $row['p_price'];
                        $in_production = $row['in_production'];
                        $date_added = $row['date_added'];
                        $last_modified = $row['last_modified'];

                        if($in_production == 'on'){
                            $checked = 'checked';
                        }

                        else{
                            $checked = '';
                        }

                        echo "<div>Product ID# " . $p_id . "<label style=\"font-style:italic\"> (Originally added on " . $date_added . ", last modified on " . $last_modified . ")</label></div><br/>";
                        echo "<input id=\"p_id" . $p_id . "\" class=\"text\" type=\"hidden\" name=\"p_id[]\" value=\"" . $p_id . "\"/>";

                        echo "<label>Product Name *</label><br/>";
                        echo "<div><label style=\"font-style:italic\">(Product still in production <input type=\"checkbox\" name=\"in_production[]\"" . $checked . " style=\"width:15px\"/>)</label></div>";    
                        echo "<input id=\"p_name" . $p_id . "\" class=\"text\" type=\"text\" name=\"p_name[]\" maxlength=\"20\" onfocus=\"on_focus(this)\" onblur=\"on_blur(this)\" value=\"" . $p_name . "\"/><br/><br/>";

                        echo "<label>Product Price *</label><br/>";
                        echo "<div><label style=\"font-style:italic\">(Without taxes)</label></div>";
                        echo "<input id=\"p_price" . $p_id . "\" class=\"text\" type=\"text\" name=\"p_price[]\" maxlength=\"6\" onkeypress=\"return currency(this, event)\" onchange=\"currency_format(this)\" onfocus=\"on_focus(this)\" onblur=\"on_blur(this)\" value=\"" . $p_price . "\"/><br/><br/><br/><br/>";

                    }

                ?>

            <input class="button" type="button" value="Submit" onclick="product_edit_form_check()"/><br/><br/>

        </form>
+3  A: 

The thing you have to bear in mind with HTML checkboxes is that they only POST a value if they are checked. If they are not checked, they don't get posted.

With this in mind, you should give each checkbox a name and then test for it in the POST to detect whether or not it has been passed back.

if (isset($_POST['MyCheckbox'])) {

} // else it wasn't checked!
Sohnee
I do realize that the checkboxes only post a value if checked, and to the best of my understanding that value is `on`. All of my checkboxes are in the same array, so I should be able to get the value of the checkboxes in a for loop with `$checkbox = ($_POST['checkbox'][$i]);` but that is not working...
typoknig
+3  A: 

It would be helpful if you could post some of the HTML-part so we could see how you create your form. It seems you're generating your checkboxes without indexes in your array, so all checkboxes have the name/id "checkbox[]", which is ok if you don't care about the index, but if posted, the array will be numbered starting from "0" and then counting up which is the reason why you'll get "0" and "1" posted, even if "0" and "2" were checked.

Try to give your checkboxes' name/id numbers when generating the HTML, like "checkbox[0]", "checkbox[1]", "checkbox[2]", and so on. So when checkbox 0 and 2 are checked, you should get those values (including the correct index) posted.

Select0r
I will give this a try, but my question is why is a number in between the square brackets necessary with a checkbox (like what you said `checkbox[0]`) when all of my other posts are working fine with no number in between the square brackets (like this `other_inputs[])`?
typoknig
This worked, and was an easy enough fix, but like I said in my comment above, why is it necessary to specify a number between square brackets with a checkbox but not with my other inputs? I generated the HTML the exact same way for all inputs... It doesn't make sense!
typoknig
From what I see, your p_id, p_name and p_price are not checkboxes so the array will be posted *completely* even if nothing was entered. As it was already pointed out by Sohnee, checkboxes won't be submitted if they're not checked, so your checkbox[]-array will be renumbered on POST if you don't provide indexes in your HTML.
Select0r
ok, i get it now, thanks a bunch!
typoknig
+1  A: 

Show us the HTML for the checkboxes.

Also, you have an SQL injection attack waiting to happen - a user can get any SQL they like onto the end of your query. Something like this illustrates what you should do with untrusted data:

//we're expect a number, so ensure we get one
$q_id = intval($_GET['q_id']); 

//get into the habit of quoting query params, 
//or better yet, use a wrapper library to help you
$sql="select * from products where q_id='".mysql_real_escape_string($q_id)."'";
Paul Dixon
Is the escaping necessary after having used intval though?
Svish
no, I was trying to illustrate good practice. Often the source and usage of a parameter are in different blocks of code, or indeed different files, so getting the habit of always escaping query parameters is good practice.
Paul Dixon
+1  A: 

If you declare checkbox name like (p_id[]), it's like telling PHP "I'm adding element to an array, enumerate it for me". Like in php $array[] = 't'; If you have several form elements with different names and you want to have synchronised IDs you HAVE to add index because otherwise browser will/may send only selected ones and PHP will enumerate it continuously.

You can specify indexes by using p_id[INDEX] and so on, where index is anything (I suggest numeric or alphanumeric).

Also, checkbox value can be altered and I encourage you to do it. value="1" helps, then you're sure that you get it.

<input type="checkbox" name="p_id[0]" value="1" />

In PHP you'll receive

$_POST['p_id'] ===> array(0 => 1);

et caetera.

Tomasz Struczyński
Originally I was using `1` or `0` for the value of my checkboxes because using `1` and `0` for checkboxes works good with JavaScript. Unfortunately I couldn't get it to work with PHP, and I read that the value posted by a checkbox to PHP is `on` if checked and nothing if unchecked. Thanks for your explanation though, it is becoming more clear.
typoknig