How to search multiple inputs and checkboxes with php pdo? - php

I have a search form with multiple "text" inputs currently functioning which I am trying to add checkboxes to.. After adding the checkboxes, I'm getting the following:
ERROR: Array to String Conversion
<form action='s-response.php method='get'>
<div class='cusname'><input type='text' name='cusname' class='EdtTxt' /></div>
<div class='street'><input type='text' name='street' class='EdtTxt' /></div>
Checkboxes
<?php while ($row=$query->fetch()){?>
<input type='checkbox' name='groupid[]' value='<?php echo $row['id'];?>'><?php echo $row['title'];?><?php }?>
RESPONSE PAGE
$wheres = array();
$params = array();
/* Find all Sent fields, If the field is Not Empty, add the field to the SQL query */
if (!empty($_GET['cosname'])) { $wheres[] = 'c.cname LIKE :cosname'; $params[':cosname'] = '%'.$_GET['cosname'].'%'; }
if (!empty($_GET['street'])) { $wheres[] = 'a.street LIKE :street'; $params[':street'] = '%'.$_GET['street'].'%'; }
Checkbox Part
if(!empty($_GET['groupid'])) {
foreach($_GET['groupid'] as $value){
$wheres[] = 'g.groupid = :groupid'; $params[':groupid'] = $_GET['groupid'];
}}
Query Part
/* Create the Start and End (static) parts of the query */
$q1="SELECT c.fname,a.street FROM customers c LEFT JOIN cus_address a ON c.id=a.custid WHERE c.act=1";
$q3=" GROUP BY c.id";
/* Create the Middle (dynamic) part of the query */
if (!empty($wheres)) { $q1 .= " AND " . implode(' AND ', $wheres); }
/* Combine into one query and execute */
$sql=$q1.$q3;
$query=$con->prepare($sql);
$query->execute($params);
Any idea what is causing the error?

Query Part
if(!empty($_GET['groupid'])) {
foreach($_GET['groupid'] as $i => $value){
$placeholder = sprintf(':groupid%d', $i+1);
$wheres[] = sprintf('g.groupid = %s', $placeholder);
$params[$placeholder] = $value;
}
}
In the foreach loop, you should be using $value, not $_GET['groupid'] - It's an array, remember? You're currently iterating over it.
I have edited my answer to show how to handle multiple group ids. The placeholder is unique, eg. :groupid1, :groupid2, :groupid3.

Related

PDO filter system with Ajax. Is there a better way?

I am trying to filter some inputs of the user with select boxes. I am figuring if there is a better way doing this.
if(isset($_POST['action']))
{
$sql = "SELECT * FROM occasions WHERE naam IS NOT NULL";
if(isset($_POST['merk'])){
$merk = $_POST['merk'];
$merkQuery = implode(',', array_fill(0, count($merk), '?'));
$sql .= " AND merk IN(".$merkQuery.")";
}
if(isset($_POST['brandstof'])){
$brandstof = $_POST['brandstof'];
$brandstofQuery = implode(',', array_fill(0, count($brandstof), '?'));
$sql .= " AND brandstof IN(".$brandstofQuery.")";
}
//We prepare our SELECT statement.
$statement = $pdo->prepare($sql);
if(isset($_POST['merk'])){
//Execute statement.
$statement->execute(array_merge(array_values($merk)));
}
if(isset($_POST['brandstof'])){
//Execute statement.
$statement->execute(array_merge(array_values($brandstof)));
}
if(isset($_POST['merk']) && isset($_POST['brandstof']))
{
$statement->execute(array_merge(array_values($merk), array_values($brandstof)));
}
else
{
$statement->execute();
}
}
Cause if there are many select boxes that need filtering, the code would become long. I was wondering if there is a better way of filtering multiple select boxes.
Here is an example: link
I would suggest renaming the post variables; grouping them into a single two dimensional array.
<input type="checkbox" name="data[merk][bmw]" />
<input type="checkbox" name="data[merk][skoda] />
and so forth.
What this does, is it allows you to use a foreach to iterate through whatever values are checked.
$data = $_POST['data'] ?? []; // null coalesce defaults to a blank array if post var is null
foreach($data as $category=>$val) {
settype($val, 'array');
$query = implode(',', array_fill(0, count($val), '?'));
foreach($val as $k=>$v) {
$params[] = $k;
}
// DON'T DO THIS!
$sql .= " AND $category IN(".$query.")";
}
The reason you shouldn’t do it as shown is because you should never build a query with user-supplied data.
What you can do, however, is map user-supplied data with hard-coded data.
$map = [
// form value => db field
'merk' => 'MERK',
'brandstof' => 'BRANDSTOF',
// ... etc
];
and then when building your query,
$sql .= " AND $map[$category] IN($query)";
In the meantime, you have built your parameters in $params.
—-
Bottom line, what we have done is refactor the code since we were noticing things getting repeated. For example, you were having to repeat code for each occasion(?). One solution would be to continue to check each post value and call a function to calculate the ?s. But even then, it would be repetitive to type out all those isset()s.
In retrospect, it probably would have been better to do inputs like this:
<input type="checkbox" name="data[merk][]" value="bmw" />
<input type="checkbox" name="data[merk][]" value="skoda" />
This would no doubt be more intuitive, although you would still have to build the params array.
foreach($val as $v) {
$params[] = $v;
}

How to insert value of multiple select checkbox into database

I have a multiple select checkbox but i couldnt find a way on how to insert into database which each checkbox will create new rows in database.
this is how my dropdown looks like
<select id="plant" name="plant[]" class="form-control" multiple="multiple">
<?php
$query_plant = "SELECT * FROM plant WHERE plant_enable=1 ORDER BY plant_name";
$rs_plant = DB_Query($query_plant);
while ($row_plant = DB_FetchRow($rs_plant)) {
$plant.='<option name='.$row_plant["plant_shortname"].' value='.$row_plant["plant_id"].'>' .$row_plant["plant_name"].' ['.$row_plant["plant_id"].']</option>';
}
mysql_free_result($rs_plant);
echo $plant;
?>
</select>
You can get the selected checkbox value by using the name of checkbox on form submit like:
$plants = $_REQUEST['plant'];
$plants is an array here, so use foreach() to iterate over it and for each value make a insert query or combine all values in a single query and fire that query on database.
if(isset($_POST['company'])) {
$checkbox1 = $_POST['plant'];
$chk="";
$stf_sql = "SELECT * FROM test_plant WHERE staff_id = '".$STAFF_ID."'";
$stf_res = DB_Query($stf_sql);
if(DB_RowsReturned($stf_res) > 0) {
$del_sql = "DELETE FROM test_plant WHERE staff_id = '".$STAFF_ID."'";
$del_res = DB_Query($del_sql);
}
foreach($checkbox1 as $chk1)
{
$in_ch="insert into test_plant(staff_id, plant_name, submit_dt) values ('$STAFF_ID','$chk1', Now())";
$in_res = DB_Query($in_ch);
$abc = mysql_query("SELECT * FROM test_plant");
while($abc_row = mysql_fetch_assoc($abc)) {
foreach($abc_row as $key => $value) {
echo $key;
}
}
}
} else {
echo "OK";
}

Send only filled inputs values to database via SQL

I have dozens of inputs in an HTML table one can use to enter numerical values. When submit button is pressed all inputs values are added to their corresponding column in the SQL table via post method. Value of <input name="A1> will be sent to column A1 in SQL table, <input name="A2> to column A2, and so on.
I'm currently using something like this (but with dozens of parameters) to insert data in my table :
$sql = "INSERT INTO all_stats_table (A1, A2, A3) VALUES ($A1, $A2, $A3)";
Problem with this approach is that every input needs to be filled or it will result in an SQL error. I initially used php to set all empty inputs value to 0 before sending everything to database, but I don't think this method is the most efficient way to go.
I would rather like to dynamically check which inputs are actually filled and only send their values to the table instead of converting every empty input value to 0 and having to send everything to the database.
I've already set all default values to 0 in SQL, but I don't know how to only send filled input values via SQL. I tried using a php foreach loop but I'm definitely having trouble finding the right SQL syntax.
Is what I'm trying to do possible ? If not, what would be the best practice to make this process more efficient ?
Thank you for your help
EDIT : attempt to adapt akash raigade's great solution to non-numbered SQL columns :
HTML :
<input name='name'>
<input name='address'>
<input name='age'>
PHP :
$Field_list = array ('name','address','age');
$field_string = '';
$input_string = '';
foreach ($_POST as $userInfo=>$userInfo_value) {
if (isset($userInfo)) {
if ($field_string == '') {
$field_string = $field_string.$userInfo; //problem here ?
$input_string = $userInfo_value; //problem here ?
}
else {
$field_string = $field_string.','.$userInfo; //problem here ?
$input_string = $input_string.','.$userInfo_value; //problem here ?
}
}
}
$sql = "INSERT INTO protocole_test (".$field_string.") VALUES (".$input_string.")";
echo $sql ; //check query formed
[Upgraded version]
Basic idea is that we keep NAME attribute of INPUT same as table column-name where it is gonna be stored.Then with help of input tag name and value which are filled we prepare SQL statement which have only required (FILLED) columns and values.
For given example consider following MYSQL table :
sr.no.|name|age|gender
CODE [Tested]:
<input name="name" >
<input name="age" >
<input name="gender" >
<input type='submit'>
<?php
$field_string ='';
$input_string='';
foreach ($_POST as $userInfo=>$userInfo_value){
if($userInfo_value !=''){
echo $userInfo."->".$userInfo_value;
if ($field_string == '') {
$field_string = $field_string.$userInfo;
$input_string = $userInfo_value;
}
else {
$field_string = $field_string.','.$userInfo;
$input_string = $input_string.','.$userInfo_value;
}
}
}
$sql = "INSERT INTO protocole_test (".$field_string.") VALUES (".$input_string.")";
echo $sql ; //check query formed
?>
[original answer]Have a look at following code :
<input name='a1' id='input_for_name'>
<input name='a2' id='input_for_class'>
<input name='a3' id='input_for_seat.no'>
.
.
<input name='an' id='input_for_n'>
Now
<?php
//you must be having field list to be inserted i.e
//INSERT INTO all_stats_table >>>(A1, A2, A3)<<< VALUES ($A1, $A2, $A3)
//A1,A2,A3 is field list here
//so save them into an array.
$Field_list = array ('A1','A2','A3',.......'An');
//Now get which input_field is inputted by :
$i=0;
$field_string = '';
$input_string = '';
for($i<n){
if(isset($_POST['a'.$i])){
if ($field_string == ''){
$field_string = $field_string.$Field_list[$i];
$input_string = $_POST['a'.$i];
}
else {
$field_string = $field_string.','.$Field_list[$i];
$input_string = $input_string.','.$_POST['a'$i];
}}}
$sql = "INSERT INTO (".$field_string.") VALUES (".$input_string.")";
//to check query formed
echo $sql ;
?>
Explanation :
We check which input field is FILLED , if it is field we add its FIELD into FIELD LIST and ITS VALUE in INPUT LIST finally we GENERATE SQL STATEMENT.
Just check if they are not defined or empty, and if so, define them.
if ( (!isset($_POST['A1'])) || (empty($_POST['A1']) ){
$A1 = '0';
} else {
$A1 = $_POST['A1'];
}
I'm not able to test this and it may need some debugging, but you could create a function, then call the function for each input. Something like...
function chkinput($input){
if ( (!isset($_POST[$input])) || (empty($_POST[$input]) ){
$$input = '0';
} else {
$$input = $_POST[$input];
}
return $$input;
}
// You could potentially loop through the post array
// but here I just call the function once per input
chkinput('A1');
chkinput('A2');
...
chkinput('A12');
You loop through the $_POST array and check if it has a value. If it does concatenate it to an variable. Like this:
$fields = "";
$values = "";
foreach($_POST as $key=>$value){
if($value != ''){
if($value != end($_POST)){
$fields .= $key . ", ";
$values .= "'" . $value . "', ";
}else{
$fields .= $key;
$values .= "'" . $value . "'" ;
}
}
}
$sql = INSERT INTO protocole_test ($fields) VALUES ($values) ;
Your SQL would look like :
INSERT INTO protocole_test (A1, A2, A3) VALUES ('A1', 'A2', 'A3')

Include files in PHP

Thank you for reading this and for your help in advance.
I got a simple Book-Catalogue /procedure code/, every visitor can see the book catalogue and click through out the books and check their authors BUT I've got an idea to add a feature that allows the users to write a comment to each book ONLY if they're logged. So I added a session variable $_SESSION['isLogged']. But there is a lot of code blocks that duplicates. What I need is an advice, what to do with this duplicated blocks of code. What the good practice says? And my code below is from one of the 6 files that I got. In everyfile I got this repeating of code.
So here's my code:
if (!isset($_SESSION['isLogged'])) {
echo '<div class="user-navigation">
<a href="register.php" class="user-nav" >Register now</a>
Log in
</div>
<div class="navigation1">
Add book
Add author
</div>';
$booksAndAuthors = mysqli_query($connection, 'SELECT DISTINCT * FROM books LEFT JOIN books_authors ON books.book_id=books_authors.book_id LEFT JOIN authors ON authors.author_id=books_authors.author_id');
$result = array();
while ($resultArr = mysqli_fetch_assoc($booksAndAuthors)) {
$result[$resultArr['book_id']] ['book_name'] = $resultArr['book_title']; // Reodering array
$result[$resultArr['book_id']] ['author'][$resultArr['author_id']] = $resultArr['author_name']; // Reordering array
}
echo '<table class="table"><tr><th>Book name</th><th>Author</th></tr>'; // Open table html table tags
foreach ($result as $k=>$b) { // Foreach the result array to get the book_name
echo '<tr><td>' . $b['book_name'] . '</td><td>';
$data = array(); // Create an empty array in order to fill the data inside
foreach ($b['author'] as $k => $a) { // Foreach the nested array with the authors to get the author_name displayed
$_GET['author_name'] = $a;
$data[] = '' . $a . ''; // Link is chosen by the author_id
}
echo implode(', ', $data); // Add a comma after every record
echo '</td></tr>'; // Close table cell and row
}
exit;
echo '</table>'; // Close html table tag
}
else {
echo '<div class="user-navigation">
My Profile
Log out
</div>
<div class="navigation2">
Add book
Add author
</div>';
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
$booksAndAuthors = mysqli_query($connection, 'SELECT DISTINCT * FROM books LEFT JOIN books_authors ON books.book_id=books_authors.book_id LEFT JOIN authors ON authors.author_id=books_authors.author_id');
$result = array();
while ($resultArr = mysqli_fetch_assoc($booksAndAuthors)) {
$result[$resultArr['book_id']] ['book_name'] = $resultArr['book_title']; // Reodering array
$result[$resultArr['book_id']] ['author'][$resultArr['author_id']] = $resultArr['author_name']; // Reordering array
}
echo '<table class="table"><tr><th>Book name</th><th>Author</th></tr>'; // Open table html table tags
foreach ($result as $k=>$b) { // Foreach the result array to get the book_name
echo '<tr><td>' . $b['book_name'] . '</td><td>';
$data = array(); // Create an empty array in order to fill the data inside
foreach ($b['author'] as $k => $a) { // Foreach the nested array with the authors to get the author_name displayed
$_GET['author_name'] = $a;
$data[] = '' . $a . ''; // Link is chosen by the author_id
}
echo implode(', ', $data); // Add a comma after every record
echo '</td></tr>'; // Close table cell and row
}
echo '</table>'; // Close html table tag
}
*If my question is not properly asked or you have some notices.Please let me know!
* (=
Put this code in a file then include that file at the bottom of all of the pages.
For example put the code in isLogged.php
Then on each page where the code is duplicated replace it with:
include "isLogged.php";
include is what you're looking for.
You should create a file that contains your repeated code. functions.php for example.
Then call it with one of these methods.
include "functions.php"
http://php.net/manual/en/function.include.php
include_once("functions.php")
http://php.net/manual/en/function.include-once.php
require_once("functions.php")
http://php.net/manual/en/function.require-once.php
create a function of repeated block and call when it required or create a file with the set of repeated code and use any of include,include_once,require_once to add the file.for more detail see php manual for these functions.

while($row = mysql_fetch_assoc($result)) - How to foreach $row?

I am working on a simple order system.
the peice of code I am stuck on is the following:
if (isset($_GET['cart']))
{
$cart = array();
$total = 0;
foreach ($_SESSION['cart'] as $id)
{
foreach ($items as $product)
{
if ($product['id'] == $id)
{
$cart[] = $product;
$total += $product['price'];
break;
}
}
}
include 'cart.html.php';
exit();
}
This is the code is build on a preset array. I am working with a table with a few columns in mysql.
I have decided on the following:
if (isset($_GET['cart']))
{
$cart = array();
$total = 0;
foreach ($_SESSION['cart'] as $id)
{
while($row = mysql_fetch_assoc($productsSql)) {
foreach ($row as $product)
{
if ($product['id'] == $id)
{
$cart[] = $product;
$total += $product['price'];
break;
}
}
}
include 'cart.html.php';
exit();
}}
To display this "cart" I have decided on this:
foreach ($cart as $item) {
$pageContent .= '
<tr>
<td>'.$item['desc'].'</td>
<td>
R'.number_format($item['price'], 2).'
</td>
</tr>
';
}
All this seems to do is produce my cart in a fashion where when viewed it displays a list of only the items' id, e.g. where the description and price are supposed to be, I only get the items id in both fields... I also get a total price of 0.
Can anyone spot where I am going wrong here?
Or atleast try to give me some input so that I get going in the right direction!
Thanks!!
$productsQuery = 'SELECT `id`, `refCode`, `desc`, `pack`, `measure`, `quantity`, `deptCode`, `taxable`, `price1`, `price2`, `crdCode`, `cost1`, `cost2` FROM `products` ORDER BY `desc` ';
$productsSql = mysql_query($productsQuery) or die(mysql_error());
if (mysql_num_rows($productsSql) == 0) {
die('No results.');
} else {
$orderContent = '';
while($row = mysql_fetch_assoc($productsSql)) {
$prId = $row['id'];
$prRefCode = $row['refCode'];
$prDesc = $row['desc'];
$prPack = $row['pack'];
$prMeasure = $row['measure'];
$prQuantity = $row['quantity'];
$prDeptCode = $row['deptCode'];
$prTaxable = $row['taxable'];
$prPrice1 = $row['price1'];
$prPrice2 = $row['price2'];
$prCrdCode = $row['crdCode'];
$prCost1 = $row['cost1'];
$prCost2 = $row['cost2'];
$orderContent .= '
<tr>
<td>'.$prId.'</td>
<td>'.$prDesc.'</td>
<td>'.$prPack.'x'.$prSize.' '.$prMeasure.'</td>
<td>R'.$prPrice1.'</td>
<td>
<form action="" method="post">
<div>
<input type="text" size="3" name="quantity" />
</div>
</form>
</td>
<td>
<form action="" method="post">
<div>
<input type="hidden" name="id" value="'.$prId.'" />
<input type="submit" name="action" value="Order" />
</div>
</form>
</td>
</tr>
';
}}
Let's say that each of the rows in your database looks like this...
[product_id][product_name][product_description][product_price]
When you assign your query return to a variable passed through mysql_fetch_assoc() using a while loop, each pass will isolate a whole row. Of which you can piece apart manually by array key reference ($array['product_id']) or by using a foreach loop. I think the problem you're having is that you are mixing this up. Keeping the above example table layout in mind, you could do something like the following:
while ($tableRow = mysql_fetch_assoc($query)) { // Loops 3 times if there are 3 returned rows... etc
foreach ($tableRow as $key => $value) { // Loops 4 times because there are 4 columns
echo $value;
echo $tableRow[$key]; // Same output as previous line
}
echo $tableRow['product_id']; // Echos 3 times each row's product_id value
}
Look at this line in your code: if ($product['id'] == $id) { }
I think you probably mean if ($row['id'] == $id) { } instead.
Your middle code block makes no sense. You loop over session variables, and run a query each time... but it's the SAME query, and using an undefined variable to boot. Looping over a result row doesn't make much sense, as you'd be looping over the individual fields that your query returns for each row.
e.g. If your products table has just (id, name, description) as fields, then $row would be an array that looks like:
$row = array('id' => xxx, 'name' => yyy, 'description' => zzz);
When you foreach() on $row(), you'd not getting individual products, you'd be getting those fields in the row. $product would be xxx, then yyy, then zzz.
I don't know what your code is trying to accomplish - I'd guess you're trying to retrieve prices for products that a user is adding into their cart, but you're going about it in a very strange and highly inefficient manner.

Categories