0

I have checkboxes that represent the condition of a product. When a user checks for example Excellent, the value 1 is stored in a GET-variable like this:

...index.php?condition=1

Now, when the user checks multiple boxes (which has to be possible), it looks like this:

...index.php?condition=1,2,3

Obviously, I have to query my database in order to show the products corresponding to the user's choice(s).

if the user only checks one box, the statement is simple:

if (!empty($_GET['condition'])){
$sql = $sql . " AND (Condition = '".$_GET['condition']."')";
} 

But what if the user checks multiple boxes? How would the statement have to look? (is it even possible to solve it this way?

thanks!

This is the script that creates the address:

<script>
$('#condition_select input:checkbox').change(function() {
var condition = $("#condition_select input:checkbox:checked").map(function() {
    return this.value;
}).get().join(',');
$("#submit_checkboxes").find("a").attr('href', 'index.php?condition=' + condition);
}).change();
</script>

HTML:

 <div class="mutliselect" id="condition_select">
 <form method="POST" action="">
 <ul>
  <li><input type="checkbox" id="d1" value="1"'; if(strpos($_GET['condition'],'1') !== false){ echo 'checked="checked"';} echo'/><label for="d1" class="checkbox_title">Neu</label></li>
<!-- and 6 more of these -->

Is there a way to solve this without having to create a separate GET-variable for each checkbox?

Frank
  • 614
  • 1
  • 8
  • 31

1 Answers1

1

UPDATE (once more updated accrding to comments and questions updates):

Question updated, so I will update my answer to. Use explode (http://php.net/manual/en/function.explode.php), to get all values, and implode to formulate query:

$values = explode(',', $_GET['condition']);
// VALIDATE each of values to match Your type.

if (!empty($values)) {

    // $values = [1, 2, 3]
    foreach ($values as $key => $value) {
        $values[$key] = '(condition = \''.$value.'\')';
    }
    // $values = ['(condition = \'1\')', '(condition = \'2\')', '(condition = \'3\')']
    $query = implode(' OR ', $values);
    // $query = '(condition = \'1\') OR (condition = \'2\') OR (condition = \'3\')', 
    $sql = $sql . ' AND ( '.$query.' )';
}

This is Your solution I think (MYSQL multiples AND: http://forums.mysql.com/read.php?10,250552). Example of explode working:


$string = '1,2,3,4,asd,fgh';
$array = explode(',', $string);
print_r($array[0]); // 1
print_r($array[3]); // 4
print_r($array[5]); // 'fgh'  

This is a fragment of answer before edits, but I think it is worth to left it here:

Hoverwer, there are many security holes in it!!!

YOU MUST verify the user data. If someone pass in the address for example:

index.php?condition=; SHOW TABLES FROM database;

It can potentialy show some data. As You can see, user can also go to address with delete statemant, or INSERT INTO users... etc.

So in that case YOU SHOULD switch to PDO (for example) http://php.net/manual/en/pdo.prepare.php, and make prepared statements. Verify user data so if You need the number, he can pass only number.


You can use isset also: isset vs empty vs is_null. It is not a must, but sometimes can be useful. With each form you can also check for isset ($_POST['submit']) as many robots that spam POST forms, sometimes just ommit the submit button. It will decrease the amount of requests I think.


Remember that using POST and GET forms ALWAYS allow user to send his own POST / GET requests. In that case, server side verification is a MUST.


PS. Sorry for capital letters, they are used only to make it really STRONG. Verify user data ;).

Best regards.

Community
  • 1
  • 1
Jacek Kowalewski
  • 2,761
  • 2
  • 23
  • 36
  • are you sure there is no way to solve it without having to create several get-variables? I'll edit my question to show you more! Thanks for the advice! – Frank Jan 18 '15 at 13:30
  • U welcome. Update Your question please, and I will try to help :). – Jacek Kowalewski Jan 18 '15 at 13:31
  • Updated... :). Is it ok now? :) – Jacek Kowalewski Jan 18 '15 at 13:36
  • Looks good, but is it necessary to use multiple different `Condition`-table-rows? In my table I have only one row called `Condition`, as each product only has only one condition. However, you used `Condition1` and `Condition2`? – Frank Jan 18 '15 at 13:40
  • If one product can contain only one condition, use not AND but OR. Then it will show only products with condition 1, OR condition 2, OR, ... IN that case, if user checks 1, 2, 3, It will show all products that have condition 1 OR condition 2, OR condition 3. Update: more like: AND (cond = 1 OR cond = 2 OR cond = 3). – Jacek Kowalewski Jan 18 '15 at 13:42
  • so I can use `Condition` instead of `Condition1` and `Condition2` in the statements? --> yes, one product can contain only one condition, but the user can choose for example two different conditions he wants his search-results to include – Frank Jan 18 '15 at 13:44
  • I understand how the statement should look when only one condition is checked, can you maybe show me how it is supposed to look when there is for example 1,2,3,4? – Frank Jan 18 '15 at 13:50
  • Updated answer. Is it ok now? :). Query should look lie this: query AND ((condition = 1) OR (condition = 2) OR (condition = 3) OR (condition = 4)); – Jacek Kowalewski Jan 18 '15 at 13:50
  • almost done! :) sorry for the inconvenience. The problem is the `if(!empty($values)){`... According to my php, it is never empty, so the script is executed even when no checkbox is checked. When I echo `$values` without a checkbox checked, it prints `Array` – Frank Jan 18 '15 at 14:03
  • Great! Try: if (!empty($values) && isset($values[0]) && $values[0] != '')). Maybe it will help :). If this will not succeed, print_r($values) and check what it is if no checkbox is checked :). – Jacek Kowalewski Jan 18 '15 at 14:10
  • you are absolutely great! Thank you so much :-) would give you a hundred upvotes if I could. – Frank Jan 18 '15 at 14:19
  • No problem :). Thx for acceptance, and good luck with Your code! And remember, verify user input! – Jacek Kowalewski Jan 18 '15 at 14:19