Use WHERE IN with PDO PHP [closed] - php

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am trying to build a shopping cart using PHP, I get a list of IDs from the products added to the basket, I then want to query my database with these IDS using a WHERE IN SQL statement to get the details of the items added to the basket.
At the moment my query just comes back with false.
if(isset($_SESSION["cart"])) {
foreach ($_SESSION["cart"] as $id => $value) {
$ids .= $id . ',';
$count += $value['quantity'];
}
$query = $database->find_item_db($ids);
EDIT I have now changed my function to use the PDO syntax.
function find_item_db($product_code) {
$query = substr($product_code, 0,-1);
$product_codes = explode(",", $query);
$product_code_new = "(".implode("', '", $product_codes).")";
//we need to get product name and price from database.
$sql = "SELECT * FROM `Sweets` WHERE `Sweet_ID` IN :id";
$statement = $this->connection->prepare($sql);
$statement->bindParam(':id', $product_code_new);
$statement->execute();
return $done = $statement->fetchAll();
}
However this is still returning nothing, I get this error in my logs.
/var/www/html/sweetshop/partials/categories-nav.php(32): Database_Functions->find_item_db('1,10,6,23,')\n#2 /var/www/html/sweetshop/category.php(17): include('/var/www/html/s...')\n#3 {main}\n thrown in /var/www/html/sweetshop/classes/class-database-functions.php on line 139, referer: http://localhost/sweetshop/category.php?type=Chocolate
I know my connection works fine as all my other queries work perfectly.

1. Incorrect syntax
If $ids is something like:
$ids = "1,2,3,4,5";
Then the query is:
SELECT * FROM `Sweets` WHERE `Sweet_ID` IN (1,2,3,4,5)
Which is incorrect because each value needs to be wrapped in single quotes:
function find_item_db($product_code){
$query = substr($product_code, 0,-1);
//Wrap each product id
$product_codes = explode("," $product_code);
$product_codes = "'".implode("', '", $product_codes)."'";
//.......
}
That way the query will read:
SELECT * FROM `Sweets` WHERE `Sweet_ID` IN ('1', '2', '3', '4', '5')`
2. Mixing SQL APIs
mysqli_* syntax and PDO syntax are not interchangeable. bind_param() is for PDO, however your query is using mysqli.
When you are using $statement->bind_param(':id', $new);, what are you binding? There is no :id value in the query, and therefore the line is unnecessary as well as incorrect SQL query format!

Related

How to convert PDO to MYSQLi [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I'm following this tutorial, but my problem is that everything is written for PDO, but the my website is MySQLi.
I've been trying to just search for conversions on www.php.net (for example; $statement = $db->prepare($query); = $statement = $db->mysqli_prepare($query) (source))
This is my code that doesn't work:
<?php
$query = "
SELECT shape FROM inventory
";
$statement = $db->mysqli_prepare($query)
$statement->mysqli_execute();
$result = $statement->mysqli_fetch()
foreach($result as $row) {
?>
<!-- HTML code here -->
<?php } ?>
It's supposed to query the shape column from the database but I keep getting this error Fatal error:
Uncaught Error: Call to a member function stmt_init() on null in /homepages/7/d410968336/htdocs/Inventory/vendors/php/Filters/Filters.php:68 Stack trace: #0 {main} thrown in /homepages/7/d410968336/htdocs/Inventory/vendors/php/Filters/Filters.php on line 68
(in this case line 7 $statement = $db->mysqli_prepare($query))
Well, first in a simple select query you really don't need the prepared statement. but if you wanna do I think this would help you.
$query = "SELECT shape FROM inventory";
$statement = mysqli_prepare($db, $query);
mysqli_stmt_execute($statement);
while(mysqli_stmt_fetch($statement)){
....
}

Converting query to parametrised query [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have a query on my site and have recently been hacked because of it.
I have spent a good 2 hours looking how to convert this query so it is secure and have not got anywhere.
If anyone don't mind, could you please convert this one for me just so I can see what to do on the rest?
$camera_id = $_GET['camera_id'];
$cameras = mysqli_query($conn, "SELECT * FROM cameras WHERE id = $camera_id");
$camera = mysqli_fetch_array($cameras);
Try something like this.
$camera_id = $_GET['camera_id'];
$cameras = mysqli_prepare($conn, "SELECT * FROM cameras WHERE id = ?");
mysqli_stmt_bind_param($cameras, $camera_id);
$cameras->execute();
While you are making the switch, switch straight away to PDO. It's far better than mysqli
$db = new PDO('mysql:host=localhost;dbname=mydb', 'username', 'password');
$stmt = $db->prepare("SELECT * FROM cameras WHERE id = :camera_id");
$stmt->execute(array(":camera_id"=>$camera_id));
$result = $stmt->fetchAll();
or instead of fetchAll()
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo $row['field1'].' '.$row['field2']; //etc...
}
As you can see this is more readable. And if you later decide eto switch to postgresql the change is real easy.
This is using PDO and assumes that the camera id is a number (if it can contain non-numerical values swap the PARAM_INT for a PARAM_STR. The basic premise is that you separate the query from the variables and you bind the value of the desired item to a variable. Also note that you would need to alter the variables in the new PDO declaration to suit your own database. Note also that fetchAll() provides an associative array of the returned results - there are a number of other fetch() methods possible to give different outcomes - look for the official documentation.
$camera_id = $_GET['camera_id'];
$conn = new PDO('mysql:host=localhost;dbname=db', 'username', 'password');
$sql = "SELECT * from cameras where id = :cameraId";
$q = $conn->prepare($sql);
$q -> bindValue(":cameraId" , $camera_id, PDO::PARAM_INT);
$q->execute();
$cameraRows = $q->fetchAll();
foreach($cameraRows as $cameraRow){
$CID= $cameraRow["camera_id"];
//.... rest of the code
}

PDO issues with binding IN operator [duplicate]

This question already has answers here:
Can I bind an array to an IN() condition in a PDO query?
(23 answers)
Closed 7 years ago.
Note: I see this question as a probable serious issue in PDO Drivers. I can pretty much understand the difference between an array and string. So, please consider testing this on your sandbox before Deleting or making duplicate.
$pdo = db()->getInstance();
$sql = "SELECT * FROM clients WHERE client_id IN :clients";
$params = [ ":clients" => "(223,224,225)" ];
$stmt = $pdo->prepare($sql);
try{
$stmt->execute($params);
} catch( \Exception $e){
die("Query Execution Failed" . $e->getMessage());
}
Query Execution FailedSQLSTATE[42000]: Syntax error or access
violation: 1064 You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right syntax to
use near ''(223,224,225)'' at line 1
The issue here is instead of translating to:
SELECT * FROM clients WHERE client_id IN (223,224,225)
it is translating to:
SELECT * FROM clients WHERE client_id IN '(223,224,225)'
There are no arrays here. I am just providing a parameter clients to replace :clients. Why does it add the quotes around?
First of all, I agree with you (somewhat). It's a issue, not very serious one. Maybe they kept it knowingly. Or, maybe your stupid question has some debate potentials.
Every PDO parameter gets wrapped with quotes. (Personally I think should not be). When you pass the IN string at once, it puts quote around it which fails the query. But, you can do that (put quotes) with individual item. So, pass parameter to each item instead of preparing string before.
Now, to the solution:
$pdo = db()->getInstance();
$sql = "SELECT * FROM clients WHERE client_id IN :clients";
$clients = [223,224,225];
/* You could use bind with ? here. I am just making this with named parameters so that you could echo SQL */
$params = [];
$replacement = [];
foreach ($clients as $key => $value){
$replacement[] = ":client$key";
$params[":client" . $key] = $value;
}
$sql = str_replace(":clients", "(" . implode(",",$replacement) . ")", $sql);
echo $sql;
/* SELECT * FROM clients WHERE client_id IN (:client0,:client1,:client2) */
$stmt = $pdo->prepare($sql);
try{
$stmt->execute($params);
print_pre($stmt->fetchAll(PDO::FETCH_ASSOC));
} catch( \Exception $e){
die("Query Execution Failed" . $e->getMessage());
}
This works like a charm. I tried by creating a dummy clients table. But the thing is your actual SQL now becomes:
SELECT * FROM clients WHERE client_id IN ('223','224','225')
Most people might not give a shit about it but you might lose some performance because the query is converting the id to string with quotes, especially you have a large database, complex queries and prefer integers.

MySQLi prepared statement executes twice on insert [duplicate]

This question already has answers here:
Insert query on page load, inserts twice?
(3 answers)
Closed 2 years ago.
I usually don't post detailed versions of my code; however, in this case it may be necessary to figure out the problem. I have a class method that I cannot stop from executing twice. Is there any particular information I am missing on MySQLi prepared statements? I have read similar questions that asks the same to no avail.
I previously asked a question about using eval for dynamic queries in prepared statements as far as it's convention and best practices. I was told to use call_user_func_array() and it worked perfectly; however, I failed to notice that the statement executed twice each time, even with the old eval() code. So I put together a snippet of my ACTUAL code which should pretty much explain itself through my comments
function insert($table, $query)
{
/**
*
* This code assumes you have a MySQLi connection stored in variable $db
* USAGE: insert(table, array('field' => 'value');
*
**/
// Sets the beginning of the strings for the prepared statements
$fields = $values = "(";
$types = "";
$params = array();
foreach($query as $key => $val)
{
// array keys = fields, and array values = values;
$fields.= $key;
// concatenate the question marks for statement
$values.= "?";
// concatenate the type chars
$types.= is_string($val) ? "s" : (is_int($val) ? "i" : (is_double($val) ? "d" : "b"));
// pass variables to array params by reference for call_user_func_array();
$params[] = &$query[$key];
if($val == end($query))
{
$fields .= ")";
$values .= ")";
array_unshift($params, $types);
}
else
{
$fields .= ", ";
$values .= ", ";
}
}
$str = "INSERT INTO {$table} {$fields} VALUES {$values}";
if($stmt = $db->prepare($str))
{
call_user_func_array(array($stmt, 'bind_param'), $params);
/**
*
* This is where I am pulling my hair out of my head and being 3
* nothces away from banging my own head into the screen and
* being without a computer at all.
*
* I have tried everything I can think of. I gotta be missing
* something
*
* IT JUST KEEPS SENDING 2 ROWS DANG IT!
*
**/
/////////////////////
$stmt->execute();//// <---Help is needed here
/////////////////////
//-- Close connection;
$stmt->close();
}
else
{
//-- Send a nice readable error msg
die("<center><h3>FAULTY QUERY STRING</h3><h4>Please check query string</h4><p>{$str}</p>");
}
}
Changed code format from OOP to regular function for testing without having to create a class.
old question, but people might still stumble upon it, I did.
I think the mysqli_query function is mainly for retrieving data, I had the same problem, and fixed it by using mysqli_real_query on insert and update queries.

Wordpress prepared LIKE query [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm trying to use a prepared LIKE query within Wordpress, but it doesn't seem to be working. I've followed the codex for the syntax.
public function userByJobId($id){
global $wpdb;
$result = $wpdb->get_row($wpdb->prepare( "SELECT * FROM use_users WHERE use_job_id LIKE = d%;", '%' . $wpdb->esc_like((int)$id)) . '%');
if(!empty($result)){
return $result;
}
return false;
}
Calling the method like so:
$userid = 1
$user = new Users();
$user_id = $user->userByJobId($userid);
Cant see where the issue lies..
A few points have been made already:
Syntax for prepare() is the same as that for sprintf; a decimal placeholder is %d, not d%
The LIKE keyword shouldn't be followed by an equals, just the expression to test against
A few other things:
You concatenate the LIKE % wildcard after the closing parenthesis for prepare(), where it should be concatenated before
get_row() will return an object by default, not just the ID, which is a property of the object returned
public function userByJobId($id){
global $wpdb;
$result = $wpdb->get_row(
$wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}users WHERE {$wpdb->prefix}job_id LIKE %d;",
'%' . $wpdb->esc_like((int)$id) . '%'
)
);
if($result){
return $result->ID;
}
return false;
}
The wordpress class reference tells me that:
Possible format values: %s as string; %d as integer (whole number);
and %f as float.
When you want to prepare a query with a like comparison you should double escape percentages.
So change
$result = $wpdb->get_row($wpdb->prepare( "SELECT * FROM use_users WHERE use_job_id LIKE = d%;", '%' . $wpdb->esc_like((int)$id)) . '%');
To
$result = $wpdb->get_row($wpdb->prepare( "SELECT * FROM use_users WHERE use_job_id LIKE %%%d%%;",(int)$id));
You also don't have to escape values (the prepare method does that for you).
Warning: Non tested code

Categories