This question already has an answer here:
PHP: 7 PDO fetch(All) tries to convert types to associated type
(1 answer)
Closed 6 years ago.
I'm converting some existing code from mysqli to PDO to use prepared statements/bind variables to help prevent SQL injection on queries, but I've run into a problem with fetching the results and using json as input to JavaScript.
After executing the query, I use this code to build the results array:
$stmt->setFetchMode(PDO::FETCH_ASSOC);
while($row = $stmt->fetch()) {
$json[] = $row;
}
echo json_encode($json);
The problem is that it seems any of my database columns that are not strings are returned without double quotes around them, unlike when I used mysqli, which wrapped all values in double quotes. How do I fix this? Is there a way to get the results with all the values as strings?
Here's the comparison of results - note that 'ID' is my auto number column and in the PDO results it is NOT wrapped in double quotes:
PDO
[{"ID":55,"Entry_Form_Number":1005,"Barcode_Text":"2017-1005","Entrant_Name":"aa
bb","Model_Name":"cc","Category_Name":"Dioramas","Paid":1,"DatePaid":"09-Feb-17
11:28AM","DateCreated":"03-Feb-17
01:11PM","DateLastUpdated":"09-Feb-17
11:28AM","LastUpdatedBy":"wf_boxoffice"},{"ID":56,"Entry_Form_Number":1006,"Barcode_Text":"2017-1006","Entrant_Name":"aa
bb","Model_Name":"cc","Category_Name":"Dioramas","Paid":1,"DatePaid":"09-Feb-17
11:28AM","DateCreated":"03-Feb-17
01:16PM","DateLastUpdated":"09-Feb-17
11:28AM","LastUpdatedBy":"wf_boxoffice"},{"ID":59,"Entry_Form_Number":1009,"Barcode_Text":"2017-1009","Entrant_Name":"aa
bb","Model_Name":"cc","Category_Name":"Original
Sculpt/Scratchbuilt","Paid":1,"DatePaid":"09-Feb-17
11:28AM","DateCreated":"04-Feb-17
10:32AM","DateLastUpdated":"09-Feb-17
11:28AM","LastUpdatedBy":"wf_boxoffice"},{"ID":62,"Entry_Form_Number":1010,"Barcode_Text":"2017-1010","Entrant_Name":"aa
bb","Model_Name":"cc","Category_Name":"Dioramas","Paid":1,"DatePaid":"09-Feb-17
11:28AM","DateCreated":"08-Feb-17
08:31PM","DateLastUpdated":"09-Feb-17
11:28AM","LastUpdatedBy":"wf_boxoffice"},{"ID":63,"Entry_Form_Number":1011,"Barcode_Text":"2017-1011","Entrant_Name":"aa
bb","Model_Name":"cc","Category_Name":"Dinosaurs","Paid":0,"DatePaid":null,"DateCreated":"09-Feb-17
08:12PM","DateLastUpdated":"09-Feb-17
08:12PM","LastUpdatedBy":"wf_anon"},{"ID":64,"Entry_Form_Number":1012,"Barcode_Text":"2017-1012","Entrant_Name":"aa
bb","Model_Name":"cc","Category_Name":"Horror
Figures","Paid":0,"DatePaid":null,"DateCreated":"10-Feb-17
07:55AM","DateLastUpdated":"10-Feb-17
07:55AM","LastUpdatedBy":"wf_anon"}]
MYSQLI
[{"ID":"55","Entry_Form_Number":"1005","Barcode_Text":"2017-1005","Entrant_Name":"aa
bb","Model_Name":"cc","Category_Name":"Dioramas","Paid":"1","DatePaid":"09-Feb-17
11:28AM","DateCreated":"03-Feb-17
01:11PM","DateLastUpdated":"09-Feb-17
11:28AM","LastUpdatedBy":"wf_boxoffice"},{"ID":"56","Entry_Form_Number":"1006","Barcode_Text":"2017-1006","Entrant_Name":"aa
bb","Model_Name":"cc","Category_Name":"Dioramas","Paid":"1","DatePaid":"09-Feb-17
11:28AM","DateCreated":"03-Feb-17
01:16PM","DateLastUpdated":"09-Feb-17
11:28AM","LastUpdatedBy":"wf_boxoffice"},{"ID":"59","Entry_Form_Number":"1009","Barcode_Text":"2017-1009","Entrant_Name":"aa
bb","Model_Name":"cc","Category_Name":"Original
Sculpt/Scratchbuilt","Paid":"1","DatePaid":"09-Feb-17
11:28AM","DateCreated":"04-Feb-17
10:32AM","DateLastUpdated":"09-Feb-17
11:28AM","LastUpdatedBy":"wf_boxoffice"},{"ID":"62","Entry_Form_Number":"1010","Barcode_Text":"2017-1010","Entrant_Name":"aa
bb","Model_Name":"cc","Category_Name":"Dioramas","Paid":"1","DatePaid":"09-Feb-17
11:28AM","DateCreated":"08-Feb-17
08:31PM","DateLastUpdated":"09-Feb-17
11:28AM","LastUpdatedBy":"wf_boxoffice"},{"ID":"63","Entry_Form_Number":"1011","Barcode_Text":"2017-1011","Entrant_Name":"aa
bb","Model_Name":"cc","Category_Name":"Dinosaurs","Paid":"0","DatePaid":null,"DateCreated":"09-Feb-17 08:12PM","DateLastUpdated":"09-Feb-17
08:12PM","LastUpdatedBy":"wf_anon"},{"ID":"64","Entry_Form_Number":"1012","Barcode_Text":"2017-1012","Entrant_Name":"aa
bb","Model_Name":"cc","Category_Name":"Horror
Figures","Paid":"0","DatePaid":null,"DateCreated":"10-Feb-17
07:55AM","DateLastUpdated":"10-Feb-17
07:55AM","LastUpdatedBy":"wf_anon"}]
No you can't. PDO doesn't provides such method to convert result.
So if you need string you need to do strval yourself.
Related
In PHP, I pull a large amount of JSON data from a URI, then serialize it into an associative PHP array via the built-in json_decode function.
Then, I create an array:
$inserts = array();
I loop through the JSON associative array, adding a new key/value pair to my $inserts array for each item in the JSON array:
foreach($JSON_data as $key => $value) {
$inserts[] = "(".mysql_real_escape_string($value["prop1"]).","
.mysql_real_escape_string($value["prop2"]).","
.mysql_real_escape_string($value["prop3"]).")";
}
Then, I perform a bulk insert simply by imploding the inserts I already prepared:
mysql_query("INSERT INTO `MyTable` (`col1`,`col2`,`col3`) VALUES ".implode(",",$inserts));
Anyways, I found that the mysql_* family is no longer suggested to be used. So I'm wondering how this type of pattern is suppose to be accomplished using prepared statements or w/e the new accepted constructs are? My concerns are to eliminate SQL injection, and also to update MySQL as quickly as possible with fewer than 10 concurrent, open connections (preferably 1). Also, to keep things as simple and quick as possible.
Or, if there's a new pattern or preferred method to perform such a bulk transaction.
If you use a prepared statement, you can loop over your $JSON_data array with a foreach loop and run the INSERT with that chunk of the data.
Using prepared statements will reduce the overhead of building the query, simply sending the new data to the database on each iteration of the loop.
$query = mysqli_prepare("INSERT INTO `MyTable` (`col1`,`col2`,`col3`)
VALUES(?,?,?)");
foreach($JSON_data as $key => $value) {
$query->bind_param('sss',$value["prop1"],$value["prop2"],$value["prop3"];
$query->execute();
}
Note that the first argument to bind_param() tells it how many values you will be binding, as well as the type for each value.
s corresponds to string data, i corresponds to integer data, d corresponds to double (floating point), and b corresponds to binary data.
One other word of caution, do NOT quote any string data, as the s datatype tells mysql to expect a string. If you quote the ? in the prepared statement, it will tell you the number of params is wrong. If you quote the strings, it will be quoted in mysql.
EDIT:
If you want to use the same paradigm (inserting multiple rows with one query), there are ways to do it. One way is to create a class that will aggregate the bind_param calls and do one bind_param when you execute the query. Code for that is here.
Use Mysqli or PDO
Here is how you would utilize prepared statements with Mysqli
<?php
//Basic layout to using parametized queries in PHP to prevent Bobby-tables
$VARIABLE = "Some Data";
$mysqli = new mysqli("SERVER","USER","PASSWORD","DATABASE");
$query = $mysqli->prepare("SELECT COLUMN_LIST FROM TABLE WHERE COLUMN = ?");
$query->bind_param('s',$VARIABLE); //'s' for string, use i for int d for double
$query->execute();
//Get results
$query->bind_result($VARIABLE_NAMES_MATCHING_COLUMN_NAMES_GO_HERE);
$query->fetch();
echo $VARIABLE_LIST_MATCHING_COLUMN_LIST;
?>
This question already has answers here:
Use an array in a mysqli prepared statement: `WHERE .. IN(..)` query [duplicate]
(8 answers)
Build SELECT query with dynamic number of LIKE conditions as a mysqli prepared statement
(2 answers)
Closed 11 months ago.
I'm currently facing a difficulty where putting a comma-separated values to a MySQL NOT IN doesn't give me the result I was hoping for. There must be something I'm missing as I'm unsure what to search for this particular problem. Running only the MySQL code works, but passing the parameter from another PHP function didn't.
Here's the code that's giving me a problem:
$uid = 1;
$selected_uids = '1,2';
$result = $db->retrieveFollowingWithCondition($uid, $selected_uids);
...then somewhere along the code...
public function retrieveFollowingWithCondition($uid, $selected_uids) {
$stmt = $this->conn->prepare("SELECT *
FROM `friendlist`
WHERE `uid` = ? AND `buddy_uid` NOT IN (?)
GROUP BY `buddy_uid`;");
$stmt->bind_param("is", $uid, $selected_uids);
...}
I've tested just putting '2' in $selected_uids and it actually works. But once there's comma involved, the code runs but the $selected_uids are still in the result. Not sure this is a bad practice or just needing a minor adjustment to the code. Anyway, I'm really looking forward to understand why it's not working for me.
By using s in bind_param you are telling PHP to treat the entire contents of $selected_uids as a string. Therefore, "1,2" is treated as ('1,2') instead of (1,2). Your problem is that bind_param doesn't support arrays, so support of IN queries is limited. There are a number of alternatives to get around this limitation, but since you are dealing with a list of ints, I would probably do a raw string concat.
// using is_numeric because is_int("1") === false
$filtered = array_filter('is_numeric', $selected_uids);
// You could also just call array_map('intval', $selected_uids);
// Depending on your needs.
if(!$filtered) {
return; // No valid values
}
$filteredStr = implode(',', $filtered);
$stmt = $this->conn->prepare("SELECT *
FROM `friendlist`
WHERE `uid` = ? AND `buddy_uid` NOT IN ($filteredStr)
GROUP BY `buddy_uid`;");
Should also be noted: if I were trying to use strings for an IN query, I would likely do the following:
$filtered = array_map([$this->conn, 'escape_string'], $queried);
$inQuery = '\'' . implode('\',\'', $filtered) . '\'';
I find that notation cleaner and easier than a dynamically generated bind_param format string.
You should bind every parameter in IN(...) separately, but method bind_param doesn't support multiple calls. There is a nice class that can do this and you can find it on PHP documentation pages:
Custom class for multiple bind_param
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
How to escape single quotes in MySQL
(19 answers)
Closed 8 years ago.
I want to add single quotes word like "Dwi'q" and "Jum'at" in PHP MYSQL,
but I cant add that word, I try search anything but I dont found it.
my query is:
$query=mysql_query("INSERT INTO `pln`(`ppno`,`persno`,`pernum`,`psgrup`,`lv`,`pos`,`nppsimkp`,`persub`,`busrea`,`pdthr`,`gk`,`marstakey`,`bkey`,`bakun`,`numtd`,`email`,`bdate`) VALUES ('".$ppno."','".$persno."','".$pernum."','".$psgrup."','".$lv."','".$pos."','".$nppsimkp."','".$persub."','".$busrea."','".$pdthr."','".$gk."','".$marstakey."','".$bkey."','".$bakun."','".$numtd."','".$email."','".$bdate."')") or die(mysql_error());
Thanks for help.
In simple.. you can escape it with backslash..
$search_keyword="jum\'at";
but i recommend you to first sanitize the value before passing it into query.. using php function called
mysql_real_escape_string($search_keyword)
for ex;
$search_keyword=mysql_real_escape_string("jum'at");
first do this:
$a = mysql_real_escape_string("Dwi'q");
$b = mysql_real_escape_string("Jum'at");
and then run your query providing these variables in your query.
In order to insert values with ' you need to use mysqli_real_escape_string or mysql_real_escape_string. Also it better to use always when you are inserting values into DB in order to avoid SQL Injection.
And one more thing Please stop using mysql_* functions and start using mysqli_* function or PDO
Example
Using mysql_real_escape_string
$a = "some one's text";
$a = mysql_real_escape_string($a);
Using mysqli_real_escape_string
$con = mysqli_connect("localhost","dbusername","dbpassword","dbname");
$a = "some one's text";
$a = mysqli_real_escape_string($con,$a);
This question already has an answer here:
Syntax error due to using a reserved word as a table or column name in MySQL
(1 answer)
Closed 8 years ago.
Many posts similar to mine,none of them work.
Have an array $data['date'], $data['name'], $data['value'].
Trying to insert into MySQL table MyValues (Date, Name, Value)
Have tried 7-8 different methods, none working.
Would like something like
for ($a=0;$a<10;$a++) {
mysql_query("INSERT INTO MyValues('Date','Index_Name','Index')
VALUES ($data['date'][$a] ,$data['name'][$a], $data['value'][$a])"
}
Have also tried foreach, building a single string to give to MySQL, etc.
Get this error
Warning: mysql_error() expects parameter 1 to be resource, boolean given on line 45
columnName shouldn't be wrap with single quotes as they are identifiers not string literals.
INSERT INTO `Values` (Date,Index_Name,Index) VALUES (....)
one more thing, the only identifier here that needs to be wrap with backtick is the tableName VALUES because it is a Reserved Keyword.
MySQL Reserved Keywords List
When to use single quotes, double quotes, and backticks in MySQL
As a sidenote, the query is vulnerable with SQL Injection if the value(s) of the variables came from the outside. Please take a look at the article below to learn how to prevent from it. By using PreparedStatements you can get rid of using single quotes around values.
How to prevent SQL injection in PHP?
Since Values is a reserved word, you can't use it as is for a table name. You must use backticks to enclose it. Similarly, it is not valid to use single quotes to name columns, you need backticks there too.
Try this:
$out = Array();
$esc = "mysql_real_escape_string";
foreach($data['date'] as $k=>$v) {
$out[] = "('".$esc($data['date'][$k])."', '".$esc($data['name'][$k])."', "
."'".$esc($data['value'][$k])."')";
}
mysql_query("INSERT INTO `Values` (`Date`, `Index_Name`, `Index`) values ".implode(",",$out));
try this, use $a++ not $ee++
for ($a=0;$a<10;$a++) {
mysql_query("INSERT INTO `Values` (`Date`,`Index_Name`,`Index`)
VALUES ('".$data['date'][$a]."' ,'".$data['name'][$a]."', '".$data['value'][$a]."' ")
}
First, I believe you want your query values quoted, so the result is 'value' and not just value. Example:
mysql_query("INSERT INTO Values(Date,Index_Name,Index) VALUES ('$data['date'][$a]' ,'$data['name'][$a]', '$data['value'][$a]');
If you are doing multiple queries, do something like:
$q = "INSERT INTO Values(Date,Index_Name,Index) VALUES ";
for {
// Add to the string here for each insert item
}
mysql_query($q);
Additionally, please start phasing out PHP's mysql_* library in favor of mysqli or PDO.
First of all, just use PDO/mysqli with prepared statements so you wont ever have any issues like this.
This will solve it though (column names with back-ticks instead of single quotes, and escaped data):
for ($a=0;$a<10;$a++) {
mysql_query("INSERT INTO `Values` (`Date`,`Index_Name`,`Index`)
VALUES ('".mysql_real_escape_string($data['date'][$a])."' ,
'".mysql_real_escape_string($data['name'][$a])."',
'".mysql_real_escape_string($data['value'])[$a]."'");
}
And try to avoid reserved names for your columns like indexand values.
This works:
for ($a=0;$a<10;$a++) {
mysql_query("INSERT INTO Values('Date','Index_Name','Index')
VALUES ('".$data['date'][$a]."','".$data['name'][$a]."','".$data['value'][$a]."')"
}
This question already has answers here:
How can I bind an array of strings with a mysqli prepared statement?
(7 answers)
Closed 3 years ago.
I’m moving some old code over to the new msqli interface using prepared statements, I’m having trouble with SQL statements containing the IN clause. I would just normally do this:
$ids = '123,535,345,567,878'
$sql = "SELECT * FROM table WHERE id IN ($ids)";
$res = mysql_query($sql);
Converting this to mysqli and prepared statements I have tried a number of solutions:
$ids = '123,535,345,567,878'
$ids = implode($ids,',');
$result = $msqli->prepare("SELECT foo,blar FROM table WHERE id IN (?));
$result->bind_param("i", $ids);
$result->execute();
The above fails and calculating the number of elements in the array and altering number of question marks in the SQL string and calling bind_parm for each element in the array also fails. Just using the comma separated string also fails.
I can find no good documentation in Google on this, so how have you solved the problem?
It's not possible to bind a list of variable length to a single bound variable.
Similarly, if you were to bind the string $ids you'll actually end up with:
SELECT foo,blar FROM table WHERE id IN ('123,535,345,567,878')
(Note the quotes around the list of IDs).
Creating your own query with the right number of question marks and bound parameters should have actually worked - you may need to try that again and report on the actual error.
Alternatively, this may be one of those occasions where it's unfortunately necessary to hand-craft your own SQL and not use bound parameters.
Look at the answer to a similar question that has been asked here before (second code sample):
I have an array of integers, how do I use each one in a mysql query (in php)?
It boils down to:
create the SQL string with the right amount of question marks
use call_user_func_array() to bind your array to the query string
I thought the point of prepared statements was so in this situation you could just do:
$stmt = $this->mysqli->prepare("UPDATE radcheck SET attribute = ?, value = ? WHERE username = ? AND attribute LIKE 'CS-Total-Octets%'");
foreach ($usernames as $username)
{
$stmt->bind_param('sss', $bandwidth_types[$bandwidth_type], $bandwidth_bytes, $username);
$stmt->execute();
}
$stmt->close();