PHP - add new WHERE clause to SQL statement within foreach loop - php

I've got a checkbox filter where multiple options can be 'checked'. Once they are checked they are stored in a JavaScript array and passed to the php file via ajax. From there, I'm trying to do a foreach loop to get each element in the array and add a new where condition to the SQL statement for each element, and run the query.
JavaScript
var vendors = [];
function filterResults($this)
{
var vendor = $($this).attr('data-id');
if($($this).prop('checked'))
{
var action = 'add';
vendors.push(vendor);
}
else
{
var action = 'remove';
var index = vendors.indexOf(vendor);
if(index >= 0)
{
vendors.splice(index, 1);
}
}
PHP Script that is run (filter-results.php)
if(is_array($_POST['vendors']))
{
$collaterals = $vendor->updateResults($_POST['vendors']);
var_dump($collaterals);
foreach($collaterals as $col)
{
include '../parts/item.php';
}
}
PHP Function containing foreach loop
public function updateResults($vendors)
{
try
{
$items = array();
$sql = "SELECT * FROM collaterals WHERE ";
foreach ($vendors as $ven)
{
echo $ven;
$sql .= "vendor = ".$ven." OR ";
}
$stmt = $this->db->prepare($sql);
$stmt->execute();
while($row = $stmt->fetchObject())
{
$items[] = $row;
}
return $items;
}
catch(Exception $e)
{
$e->getMessage();
}
}
The 'echo' within the PHP function is working, but the var_dump() is turning 'NULL' which means there is an error within the SQL statement somewhere.
Any help would be greatly appreciated. Thanks!

You can this run query without foreach loop as follows
$sql = "SELECT * FROM collaterals WHERE vendor IN ('".implode("','",$vendors)."')";

Your query looks like
SELECT * FROM collaterals WHERE vendor = x OR vendor = x OR
You must remove the last OR.
Also i would suggest using the IN clause with implode() php function.

it will produce "SELECT * FROM collaterals WHERE vendor = 1 OR vendor = 2 OR "
use "Select * FROM collaterals where vendor in(1,2,3)" instead,

Problems:
You're using vendor = item1 OR vendor = item2 OR (notice the hanging OR)
Using IN achieves the same result
You should be using prepared statements
Do this:
$items = array();
$sql = "SELECT * FROM collaterals WHERE vendor IN (".
implode(",",array_fill(0, count($vendors), "?"))
.")";
// $sql would look like e.g. SELECT * FROM collaterals WHERE vendor IN (?,?,?)
$stmt = $this->db->prepare($sql);
$stmt->execute($vendors);
Note: All $vendors will be treated as strings in the above code, if you need to bind them as a different type you should call bindParam or bindValue on each array entry

Related

PHP changing fetch_field() to mysqli

My php knowledge is fairly limited but I've recently needed to update a number of web pages from an older version of php 5.2 to php 7.3.
I've managed to update most of the mysql references to mysqli etc and get things working correctly, however there is one page that makes use of a calendar and I'm really struggling with this section and the fetch_field part in particular as any examples I have found don't seem to be in a similar format.
The code I need to update is below;
require_once('Connections/connAsh.php');
mysql_select_db($database_connAsh, $connAsh);
function selectonerow($fieldsarray, $table, $uniquefield, $uniquevalue)
{
//The required fields can be passed as an array with the field names or as a comma separated value string
if (is_array($fieldsarray)) {
$fields = implode(", ", $fieldsarray);
} else {
$fields = $fieldsarray;
}
//performs the query
$result = mysql_query("SELECT $fields FROM $table WHERE $uniquefield = '$uniquevalue'") or die("Could not perform select query - " . mysql_error());
$num_rows = mysql_num_rows($result);
//if query result is empty, returns NULL, otherwise, returns an array containing the selected fields and their values
if ($num_rows == NULL) {
return NULL;
} else {
$queryresult = array();
$num_fields = mysql_num_fields($result);
$i = 0;
while ($i < $num_fields) {
$currfield = mysql_fetch_field($result, $i);
$queryresult[$currfield->name] = mysql_result($result, 0, $currfield->name);
$i++;
}
return $queryresult;
}
}
My attempts at editing this are;
require_once('../Connections/connAsh.php')
$connAsh->select_db($database_connAsh);
function selectonerow($fieldsarray, $table, $uniquefield, $uniquevalue)
{
//The required fields can be passed as an array with the field names or as a comma separated value string
if (is_array($fieldsarray)) {
$fields = implode(", ", $fieldsarray);
} else {
$fields = $fieldsarray;
}
//performs the query
$result = $connAsh->query("SELECT $fields FROM $table WHERE $uniquefield = '$uniquevalue'") or die("Could not perform select query - " . mysqli_error());
$num_rows = mysqli_num_rows($result);
//if query result is empty, returns NULL, otherwise, returns an array containing the selected fields and their values
if ($num_rows == NULL) {
return NULL;
} else {
$queryresult = array();
$num_fields = mysqli_num_fields($result);
$i = 0;
while ($i < $num_fields) {
$currfield = mysqli_fetch_field($result);
$queryresult[$currfield->name] = mysqli_fetch_array($result, MYSQLI_BOTH);
$i++;
}
return $queryresult;
}
}
The original function is wrong on so many levels. And there is no point in recreating its functionality.
Basically all you are bargaining for here is just a few SQL keywords. But these keywords contribute for readability.
For some reason you decided to outsmart several generations of programmers who are pretty happy with SQL syntax, and make unreadable gibberish
$row = selectonerow("some, foo, bar", "baz", "id", [$uniquevalue]);
instead of almost natural English
$row = selectonerow("SELECT some, foo, bar FROM baz WHERE id=?", [$uniquevalue]);
Come on. It doesn't worth.
Make your function accept a regular SQL query, not a limited unintelligible mess.
function selectonerow(mysqli $conn, string $sql, array $params = []): array
{
if ($params) {
$stmt = $conn->prepare($sql);
$stmt = $mysqli->prepare($sql);
$stmt->bind_param(str_repeat("s", count($params), ...$params);
$stmt->execute();
$result = $stmt->get_result()
} else {
$result = $conn->query($sql);
}
return $result->fetch_assoc();
}
This function will let you to use any query. For example, need a row with max price?
$row = selectonerow("SELECT * FROM baz ORDER BY price DESC LIMIT 1");
Need a more complex condition? No problem
$sql = "SELECT * FROM baz WHERE email=? AND activated > ?";
$row = selectonerow($sql, [$email, $date]);
and so on. Any SQL. Any condition.
I would recommend to get rid of this function or replace it with a function suggested by YCS.
If you really want to continue using this function consider the following fixes. You made the code inside extremely complicated and you forgot to pass the connection variable into the function. I have simplified it:
// open the DB connection properly inside Connections/connAsh.php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$connAsh = new mysqli('host', 'user', 'pass', $database_connAsh);
$connAsh->set_charset('utf8mb4');
// your function:
function selectonerow(mysqli $connAsh, $fieldsarray, $table, $uniquefield, $uniquevalue): array
{
//The required fields can be passed as an array with the field names or as a comma separated value string
if (is_array($fieldsarray)) {
$fields = implode(", ", $fieldsarray);
} else {
$fields = $fieldsarray;
}
//performs the query
$stmt = $connAsh->prepare("SELECT $fields FROM $table WHERE $uniquefield = ?");
$stmt->bind_param('s', $uniquevalue);
$stmt->execute();
return $stmt->get_result()->fetch_assoc();
}
This is your function, but with a lot of noise removed. I added $connAsh in the function's signature, so you must pass it in every time you call this function. The function will always return an array; if no records are fetched the array will be empty. This is the recommended way. Also remember to always use prepared statements!

How to execute prepare statement using if statement in PHP PDO?

I am fetching some data from MySQL database using PHP PDO prepared statement. I have to use if statement inside the execution of the prepared statement. See my codes below for better understanding
$query = "SELECT * FROM my_table WHERE 1=1";
if(isset($_GET['one'])){
$query .= " AND one = :one";
}
if(isset($_GET['two'])){
$query .= " AND two = :two";
}
if(isset($_GET['three'])){
$query .= " AND three = :three";
}
$result = $db->prepare($query);
$result->execute([
/* ------------------------------------
How to declare the above parameters here
as it will show error if any of the if statement is not true?
----------------------------------------*/
]);
I want to know how to declare the prepared array parameter using if statement inside the $result->execute(......]) block?
You need to create an empty $params array, and inside each if block you can push the appropriate value to it. For example:
if(isset($_GET['one'])){
$query .= " AND one = :one";
$params[':one'] = $_GET['one'];
}
Then you can simply do
$result->execute($params);
Note that you can based on what you've written, you could simplify your code with an outer foreach on a list of parameter names e.g.
$names= array('one', 'two', 'three');
$params = array();
foreach ($names as $name) {
if (isset($_GET[$name])) {
$query .= " AND $name = :$name";
$params[":$name"] = $_GET[$name];
}
}
$result->execute($params);

how to get db all data using array in php

I create as the following function. how to get all data using this array. when run this function will appear only the first record. but, i want it to appear all the records. what is the error in this code.
public function get_All_Se($stId){
$query = "SELECT * FROM session WHERE stId = '$stId'";
$result = $this->db->query($query) or die($this->db->error);
$data = $result->fetch_array(MYSQLI_ASSOC);
return $data;
}
public function get_All_Se($stId){
$rows=array();
$query = "SELECT * FROM session WHERE stId = '$stId'";
$result = $this->db->query($query) or die($this->db->error);
while($data= $result->fetch_assoc()){
$rows[]=$data;
}
return $rows;
}
Run loop over all results and add to some return array.
$rows = array();
while(($row = $result->fetch_array($result))) {
$rows[] = $row;
}
As the documentation of mysqli::fetch_array() explains, it returns only one row (and not an array containing all the rows as you might think).
The function you are looking for is mysqli::fetch_all(). It returns all the rows in an array.
public function get_All_Se($stId)
{
$query = "SELECT * FROM session WHERE stId = '$stId'";
$result = $this->db->query($query) or die($this->db->error);
return $result->fetch_all(MYSQLI_ASSOC);
}
The code above still has two big issues:
It is open to SQL injection. Use prepared statements to avoid it.
or die() is not the proper way to handle the errors. It looks nice in a tutorial but in production code it is a sign you don't care about how your code works and, by extension, what value it provides to their users. Throw an exception, catch it and handle it (log the error, put some message on screen etc) in the main program.
Try this way...
<?php
// run query
$query = mysql_query("SELECT * FROM <tableName>");
// set array
$array = array();
// look through query
while($row = mysql_fetch_assoc($query)){
// add each row returned into an array
$array[] = $row;
// OR just echo the data:
echo $row['<fieldName>']; // etc
}
// debug:
print_r($array); // show all array data
echo $array[0]['<fieldName>'];
?>

Return a multidimensional array from MySQL result php

I have a PHP function that extract dat of an invoice from DB.
The invoice may have more then one line (one product).
function getInvoiceLines($id)
{
$res = mysql_query("select * from invoice_lines where id = $id ");
while ($row = mysql_fetch_array($res))
{
$res_retun['ref']=$row['ref'];
$res_retun['label']=$row['label'];
$res_retun['price']=$row['label'];
$res_retun['qty']=$row['qty'];
}
return $res_retun ;
}
I found this link Create a Multidimensional Array with PHP and MySQL and I made this code using that concept.
Now, how can I move something like a cursor to the next line and add more lines if there's more in MySQL result??
If it's possible, how can I do to show data in HTML with for ??
A little modification should get what you want, below the [] operator is a shorthand notation to add elements to an array, the problem with your code is that you are overwriting the same keys on each iteration
// fetch only what you need;
$res = mysql_query("select ref, label, price, qty from invoice_lines where id = $id ");
while ($row = mysql_fetch_array($res))
{
$res_return[] = $row;
}
return $res_return;
Note, I fixed some of your typos (you were using $rw instead of $row in the loop of your original code)
If you used PDO with fetchAll() you would be returned with the array your expecting, also be safe from nastys:
<?php //Cut down
$db = new PDO("mysql:host=localhost;dbname=dbName", 'root', 'pass');
$sql = "SELECT * FROM invoice_lines WHERE id = :id ";
$stmt = $db->prepare($sql);
$stmt->bindParam(':id', $id);
$stmt->execute();
$res_return = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
Then you just loop through the array like with any other array:
<?php
foreach($res_return as $row){
echo $row['ref'];
...
...
}
?>
Also id should not have more then 1 row it should be unique IF its your primary key.
If you were using PDO like you should be it would be super easy and you would solve your sql injection issues
$db = new PDO(...);
function getInvoiceLines( $db, $id )
{
$stmnt = $db->prepare("select ref, label, price, qty from invoice_lines where id=?");
$stmnt->execute( array( $id ) );
return $stmnt->fetchAll( PDO::FETCH_ASSOC );
}
Make variable global first Then access it in function. For exp.
$return_arr = array(); // outside function
$i = 0;
cal_recursive(); // call function first time
function cal_recursive(){
global $return_arr;
global $i;
$return_arr[$i] = // here push value to array variable
$i++;
// do code for recursive function
return $return_arr // after end
}

How do you create a simple function to query the database? Mine isn't working!

I want to make a simple function that I can call on to query my database. I pass the "where" part of the query to it and in the code below, my $q variable is correct. However, what should I then do to be able to use the data? I'm so confused at how to do something I'm sure is extremely easy. Any help is greatly appreciated!
function getListings($where_clause)
{
$q = "SELECT * FROM `listings` $where_clause";
$result = mysql_query($q,$dbh);
foreach (mysql_fetch_array($result) as $row) {
$listingdata[] = $row;
}
return $listingdata;
}
Your function should be like this:
function getListings($where_clause, $dbh)
{
$q = "SELECT * FROM `listings` $where_clause";
$result = mysql_query($q, $dbh);
$listingdata = array();
while($row = mysql_fetch_array($result))
$listingdata[] = $row;
return $listingdata;
}
Improvements over your function:
Adds MySQL link $dbh in function arguments. Passit, otherwise query will not work.
Use while loop instead of foreach. Read more here.
Initialize listingdata array so that when there is no rows returned, you still get an empty array instead of nothing.
Do you have a valid db connection? You'll need to create the connection (apparently named $dbh) within the function, pass it in as an argument, or load it into the function's scope as a global in order for $result = mysql_query($q,$dbh); to work.
You need to use while, not foreach, with mysql_fetch_array, or else only the first row will be fetched and you'll be iterating over the columns in that row.
$q = "SELECT * FROM `listings` $where_clause";
$result = mysql_query($q,$dbh);
while (($row = mysql_fetch_array($result)) != false)
{
$listingdata[] = $row;
}
Always add error handling in your code. That way you'll see what is going wrong.
$result = mysql_query($q,$dbh);
if (!$result) {
trigger_error('Invalid query: ' . mysql_error()." in ".$q);
}
Here is a function which will save you some time. First Argument tablename, then condition(where), fields and the order. A simple query will look like this : query_db('tablename');
function query_db($tbl_name,$condition = "`ID` > 0",$fields = "*",$order="`ID` DESC"){
$query="SELECT ".$fields." FROM `".$tbl_name."` WHERE ".$condition." ORDER BY".$order;
$query=$con->query($query);
$row_data=array();
while($rows = $query->fetch_array()){
$row_data[] = $rows;
}
return $row_data;
}

Categories