How to debug the concatenation of a SQL query in PHP? - php

There's something with my query, but I cannot manage to find what.
$keys = array_keys($fields);
$values = array_values($fields);
$sql = "UPDATE " .$table. " SET " .implode("`, `", $keys) ."='".implode("', '", $values) . "' WHERE id={$id}";
And it shows as : UPDATE users SET name, password'Rick is vets', 'sdfg' WHERE id=5
But it has to show as : UPDATE users SET name = 'Rick is vets', password='sdfg' WHERE id=5

Try looping through the $fields array to create an update string like this:
$update_string='';
foreach ($fields as $key=>$value)
{
$update_string .= $key."='$value', ";
}
Then remove the last comma character from the string using rtrim() function:
$update_string = rtrim($update_string, ", ");
Then your query becomes:
$sql = "UPDATE " .$table. " SET " .$update_string. " WHERE id={$id}";
This is just to illustrate the concept since your code might still be
open to SQL injection attacks, in which case you should use prepared
statement.

$setString='';
foreach($fields as $k=>$v){
$setString .=$k." = '".$v."', ";
}
$setString=rtrim($setString,', ');
include $setString in query

Related

Advice on Prepared-Statements and Joins

I'm trying to build a back end solution to a web page project for a class i'm taking. The class doesn't cover anything about back end coding so I've had to learn everything myself. I want to understand how to utilize prepared statements and joins in the PHP code below. There are three tables in my database, but i only want back the data from one of them and only sometimes need to reference the other two to hone in my search.
The code currently works as expected, but is vulnerable to sql injection. I'm getting three form inputs from the user: a text input ($_POST["spell_name"]), a select element ($_POST["classList"]), and some checkboxes ($_POST["school"]). It still needs to work when the checkbox sends an empty array (none of the checkboxes are checked) and the select element sends the default value "all".
$sql = "SELECT * FROM dnd5_spells WHERE ";
if($_POST["classList"] != "all"){
$sql .= "spell_id= ANY(SELECT spell_id FROM dnd5_class_spells WHERE class_id = ANY(SELECT class_id FROM dnd5_classes WHERE class_name='{$_POST["classList"]}')) AND";
};
$sql .= " spell_name LIKE '%{$_POST["spell_name"]}%'";
if(!empty($_POST["school"])){
$sql .= " AND (";
$spellschools = $_POST["school"];
$valueLength = count($spellschools);
for ($x = 0; $x < $valueLength; $x++) {
if ($x>0) {
$sql.= " OR";
};
$sql .= " spell_type" . " LIKE" . " '%" . $spellschools[$x] . "%'";
};
$sql .= ")";
};
$result = mysqli_query($conn, $sql);
How do i make a prepared statement when i can receive all or none of the possible input values and i don't know what i'm getting ahead of time (in my case sending the form data blank returns the entire table and this is good)? Can i iterate over an array into a prepared statement when the array can either be empty or have multiple values? Should i be concerned about including sections of the sql query when that part of the query isn't needed?
Also, i know my use of ANY could possibly be replaced with a JOIN, but i couldn't wrap my head around it and it's less important to me than figuring out the prepared statement issue.
Here is the solution I found. I needed to use PDO then build my statement as I went with prepared statements in mind, placing ? where I wanted my input data, and at the same time build an array with the corresponding data values. I doubt it's perfect but it works just as well as my initial code and is less susceptible to SQL injection.
$sql = "SELECT * FROM dnd5_spells WHERE ";
$parameters = [];
if($_POST["classList"] != "all"){
$sql .= "spell_id= ANY(SELECT spell_id FROM dnd5_class_spells WHERE class_id = ANY(SELECT class_id FROM dnd5_classes WHERE class_name= ?)) AND";
$parameters[] = $_POST["classList"];
};
$sql .= " spell_name LIKE ?";
$parameters[]= "%" . $_POST["spell_name"] . "%";
if(!empty($_POST["school"])){
$sql .= " AND (";
$spellschools = $_POST["school"];
$valueLength = count($spellschools);
for ($x =0; $x < $valueLength; $x++){
if ($x>0){
$sql.= " OR";
};
$sql.= " spell_type LIKE ?";
$parameters[] ="%" . $spellschools[$x] . "%";
};
$sql .= ")";
};
//bind the peramaters into the prepared statment
$stmt = $conn->prepare($sql);
$stmt->execute($parameters);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

How to add value to row by id sql

I have two arrays with ID and description.
In database I have same ID but doesn't have description.
How I can add each description form array to current ID?
This is full code
foreach($product->find('.block-d .btns-d .btn-buy') as $productId) {
if(!empty($productId)) {
dataId = $productId->{'data-offerid'};
}
}
foreach($product->find('.description div div p') as $description) {
if(!empty($description)) {
$query = "UPDATE snowcore_parser_products SET description = " . $description . " WHERE remote_id = " . $dataId . " ';";
$sql = mysqli_query($db, $query);
}
}
If I try to use just simple value without array it works. For example
$query = "UPDATE snowcore_parser_products SET description = '1';";
I think your query is malformed. It doesn't have quotes around the description to indicate it is a string. For example, if the value for description is "stackoverflow" and the id is "1", your query would look like so:
UPDATE snowcore_parser_products SET description = stackoverflow WHERE remote_id = 1 ';
So to fix this, the last quote should disappear and the value for description should be surrounded with quotes. Like this:
$query = "UPDATE snowcore_parser_products SET description = '" . $description . "' WHERE remote_id = " . $dataId . ";
Also I recommend you to read this article on SQL injection, as this query isn't safe.
just use foreach and that`s all, try this:
$ids = [1,2,3];
$descriptions = [1,2,3];
foreach($ids as $key => $id) {
$query = "UPDATE snowcore_parser_products SET description = " . $descriptions[$key] . " WHERE remote_id = " . $id . " ';";
$sql = mysqli_query($db, $query);
}

PHP: How to pass multiple values to SELECT query

I am new to PHP and hope someone can help me with this.
I currently use the below lines to retrieve a value from a db and to output it as an array with the item's ID and value which works as intended.
Now I would need to do the same for multiple items so my input ($tID) would be an array containing several IDs instead of just a single ID and I would need the query to do an OR search for each of these IDs.
I was thinking of using a foreach loop for this to append " OR " to each of the IDs but am not sure if this is the right way to go - I know the below is not working, just wanted to show my thoughts here.
Can someone help me with this and tell me how to best approach this ?
My current PHP:
$content = "";
$languageFrm = $_POST["languageFrm"];
$tID = $_POST["tID"];
$stmt = $conn->prepare("SELECT tID, " . $languageFrm . " FROM TranslationsMain WHERE tID = ? ORDER BY sortOrder, " . $languageFrm);
$stmt->bind_param("s", $tID);
$stmt->execute();
$result = $stmt->get_result();
while($arr = $result->fetch_assoc()){
$content[] = array("ID" => $arr["tID"], "translation" => $arr[$languageFrm]);
}
My thought:
foreach($tID as $ID){
$ID . " OR ";
}
Many thanks for any help,
Mike
There are two approaches, assuming $tID is an array of IDs
Using MySQL IN() clause
This will work also when $tID is not an array, but a single scalar value.
$tID = array_map('intval', (array)$tID); // prevent SQLInjection
if(!empty($tID)) {
$query .= ' WHERE tID IN(' . implode(',', $tId) . ')';
} else {
$query .= ' WHERE 0 = 1';
}
Using OR clause, as you suggested
A bit more complicated scenario.
$conds = array();
foreach($tID as $ID) {
$conds[] = 'tID = ' . intval($ID);
}
if(!empty($conds)) {
$query .= ' WHERE (' . implode(' OR ', $conds) . ')';
} else {
$query .= ' WHERE 0 = 1';
}
As per above conditions you can try with implode();
implode($tID,' OR ');
You can also use IN condition instead of OR something like this.
implode($tID,' , ');

Setting up SQL queries with multiple parameters

I need to set up a SQL query with multiple parameters that are being pulled from the URL. So far I can only get it to work with the there is only one item in the URL.
My default query to pull in all the content
$sql = "SELECT ";
$sql .= "* ";
$sql .= "FROM ";
$sql .= "cms_site_content ";
$sql .= "WHERE ";
$sql .= "1";
I then check if anything was passed through the URL and retrieve it.
if (isset($_GET["d"])) {
$d=$_GET["d"];
Inside the if statement, I break the values passed as "d" into separate items
$newD = explode(',',$d);
$countD = count($newD);
foreach($newD as $discipline) {
if ($countD == 1) {
$sql .= " AND";
$sql .= " discipline='".$discipline."'";
}
My problem is getting the SQL to work if there is more than one discipline value. It should read something like this:
SELECT * FROM cms_site_content WHERE 1 AND discipline="value"
however if there's more than one discipline value, it should read:
SELECT * FROM cms_site_content WHERE 1 AND discipline="value OR discipline="value2" OR discipline="value3"
Is there a more efficient way to write this? I can't figure out how to insert the OR into the foreach statement.
Save all discipline values in an array;
$discipline_arr = array();
foreach($newD as $discipline) {
$discipline_arr[] = $discipline;
// by the way, don't forget to escape for sql injection
// mysql_escape_string is the depracated one, u can use that if u have no
// other choice
}
Then in your sql, add them as discipline in ('value1','value2', 'etc ...') condition (that is for strings, for numeric types it would be like discipline in (1,2,3,4, etc)
$sql = " SELECT * FROM cms_site_content WHERE 1 " .
(empty($discipline_arr) ? "" : "and
discipline in ('". implode("','" , $discipline_arr). "') ") ;
Link to escaping
http://tr1.php.net/manual/en/function.mysql-escape-string.php
Assuming the rest of your query is in tact. Simply store all of your discipline values in an array as follows, then feed the $discipline_string to your $sql query:
$discipline_ary = array('option1', 'option2', 'option3');
$discipline_string = "";
for($i=0; $i < count($discipline_ary); $i++){
$discipline_string .= " discipline = '" . $discipline[$i] . "' ";
if($i+1 == count($discipline_ary)){
break;
}else{
$discipline_string .= " OR "
}
}

how can I avoid to many OR statements in a mysql query?

I am writing a code, where I have to produce a query with many OR statements, and I think there is a more comfortable way to this than:
foreach ($plz as &$value) {
if (empty($i)) {
$query = "WHERE plz='$value'";
} else {
$query = "$query OR plz='$value'";
}
$i++;
}
$sql = mysql_query("SELECT * FROM table $query");
while ($data = mysql_fetch_array($sql)) {
//do something
}
If you have multiple values a column may take, just connect them using the IN operator:
Instead of writing
... WHERE col=1 OR col=2 OR col=3
just write
... WHERE col IN (1,2,3)
To collect all entries in PHP, use an array and implode() later on:
// collecting values
$vals = array();
$vals[] = 1;
$vals[] = 2;
// ...
// add them to your query
$query .= ' WHERE col IN ( ' . implode( ',', $vals ) . ')';
// execute the query ...
In case your values are not integer, but need to be enclosed in apostrophes within the query, insert them that way into the array in the first place:
$vals[] = "'my string value'";
You're looking for ;
SELECT * FROM table WHERE plz in ('value1', 'value2', 'value3')
Be aware of SQL injections...
If the column plz is INT type, and all $plz are also integers, then:
$query = 'WHERE plz IN( ' . implode(',', $plz) . ')';
would work. Otherwise, trying this might work(not tested):
$query = 'WHERE plz IN( \'' . implode("','", $plz) . '\')';

Categories