PDO statement, quotes are stored as? - php

So, I'm really new to PDO, and I was trying some stuff and practicing it, and happens that I became really confuse about what is happening to my database once I'm trying to insert some special characters with this code below:
<?php
$post_cat = 4;
$post_title = "TESTING";
$post_author = "Test";
$post_image = "test_image.png";
$post_content = "“Luo Changan, I grant you five breaths’ time. Show me whether you’re actually such a ‘person’ as you say, or a dog that would ‘beg to surrender!’”";
$post_tags = "novel, mga, chinese novel";
$ID_post_stat = 2;
$pdo = new PDO("mysql:charset=utf8mb4;hostname=localhost;dbname=cms;", "root", "");
$stmt = $pdo->prepare('INSERT INTO posts (ID_post_category, post_title, post_author, post_image, post_content, post_tags, ID_post_status) VALUES (?, ?, ?, ?, ?, ?, ?)');
$stmt->bindParam(1, $post_cat);
$stmt->bindParam(2, $post_title);
$stmt->bindParam(3, $post_author);
$stmt->bindParam(4, $post_image);
$stmt->bindParam(5, $post_content);
$stmt->bindParam(6, $post_tags);
$stmt->bindParam(7, $ID_post_stat);
$stmt->execute();
/* data stored:
+------------------+------------+-------------+----------------+-----------------------------------------+---------------------------+----------------+
| ID_post_category | post_title | post_author | post_image | post_content | post_tags | ID_post_status |
+------------------+------------+-------------+----------------+-----------------------------------------+---------------------------+----------------+
| 4 | TESTING | Test | test_image.png | ?Luo Changan, I grant you five breaths? | novel, mga, chinese novel | 2 |
| | | | | time. Show me whether you?re actually | | |
| | | | | such a ?person? as you say, or a dog | | |
| | | | | that would ?beg to surrender!?? | | |
+------------------+------------+-------------+----------------+-----------------------------------------+---------------------------+----------------+
*/
?>
I was looking for answers for why this characters (“ ‘ ’ ”) are not being stored on database and are replaced with (?) instead, I had tried to change the table and column to UTF8 as I had read some answers from the community, but it don't seems to make difference, its working fine with (áéíóú) though. Thanks in advance!
as suggested by Madhur Bhaiya, I had tried again to check on it charset, even aplied charset=utf8mb4 to my PDO DSN what helped me alot instead of using utf8_decode or utf8_encode to each string, and it is indeed all set to UTF8 already, so I guess that this kind of characters like curly quotes aren't supported for this charset, then how can I solve this?

Related

How to put multiple values in WHERE row = (?) SQL php statement [duplicate]

This question already has answers here:
How do you use IN clauses with mysqli prepared statements [duplicate]
(3 answers)
Closed 3 years ago.
So my query works on the actual phpmysql server when I manually type in some values but in php I am having some difficulty.
This is my SQL table:
userID | forename | surname | email | age |
------------------------------------------------------------
1 | Jack | Wolf | dj#rave.com | 19 |
2 | Mark | Smith | mark#rave.com | 18 |
3 | Ben | Cas | sex#club.com | 21 |
4 | Jos | Jis | jis#jos.com | 19 |
5 | Luke | Kils | kils#kiss.com | 23 |
------------------------------------------------------------
Basically, I want to pass in some UserID values like this 1,3,5 and it should display:
userID | forename | surname | email | age |
------------------------------------------------------------
1 | Jack | Wolf | dj#rave.com | 19 |
3 | Ben | Cas | sex#club.com | 21 |
5 | Luke | Kils | kils#kiss.com | 23 |
------------------------------------------------------------
The userID values can vary depending on what the user selects so it can be 2 or even 1,2,3,4 or even 1,2,3,4,5
This is my php code:
<?php
require "init.php";
if(!empty($_POST['userID'])){
$userID = $_POST['userID'];
echo $_POST['userID'];
$stmt = "SELECT userID, forename, surname, email, age
FROM users
WHERE userID IN (?)";
$result = $conn-> prepare($stmt);
$result->bind_param('i', $userID);
$result->execute();
$outcome=$result->get_result();
$response = array();
if(($outcome->num_rows)>0){
while($row = $outcome->fetch_assoc()){
$response[] = array
(
"userID" => $row["userID"],
"forename" => $row["forename"],
"surname" => $row["surname"],
"email" => $row["email"],
"age" => $row["age"]
);
}
echo json_encode($response);
}
else{
echo json_encode("None found");
}
}
?>
When I echo $userID = $_POST['userID']; I get 1,2,3 or 1, but then these are not being passed properly to the SELECT STATEMENT. How do I fix it?
Thanks
Something along these lines
...
$userIDs = implode(",",$_POST['userID']); //Array of user ids
$qs = array_fill(0,count($userIds),"?");
$stmt = "SELECT userID, forename, surname, email, age
FROM users
WHERE userID IN (".implode(",",$qs).")";
$bindParams = $userIDs; //Array for the bind parameters
$bindParams = array_unshift($bindParams, "i"); //Prefix with "i"
call_user_func_array([$result, 'bind_param'],$bindParams);
...
The idea is that your statement will need as many "?" as there are user ids since you're binding that many integers.
You'll use call_user_func_array to call the bind_param function with a variable amount of arguments. Note that if you're using PHP 5.6+ you could just do something like: $result->bind_param("i",...$userIDs)
select userName from Table where user_id in (1, 2, 3);.
you can use $_POST['userID'] in this format or convert this format and use it.

very strange duplicate entry error [duplicate]

This question already has answers here:
When to use single quotes, double quotes, and backticks in MySQL
(13 answers)
Closed 7 years ago.
I am saving data repeatedly with code. The first time I run it it doesn't complain. The second time it says Duplicate entry '$id' for key 'PRIMARY'. I am echoing $id value and they are different everytime. The table is 5min old and I guess it can't be corrupted. Is my approach wrong?
function insertData($conn,$data){
$id=$data['id'];
$name=$data['name'];
$fp=$data['first_price'];
$sp=$data['second_price'];
echo "$id<br>";
echo "$name<br>";
echo "$fp<br>";
echo "$sp<br>";
$query = 'INSERT INTO names VALUES("$id", "$name", "$fp", "$fp")';
$result = $conn->query($query);
if (!$result){
echo "nothing saved, sorry $conn->error";
}
}
table structure:
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id | varchar(15) | NO | PRI | NULL | |
| name | varchar(150) | YES | | NULL | |
| first_price | varchar(10) | YES | MUL | NULL | |
| second_price | varchar(10) | YES | MUL | NULL | |
+--------------+--------------+------+-----+---------+-------+
You're trying to insert the string literals $id etc into the table because you're using single quotes.
Here's an example that would work:
$query = "INSERT INTO names VALUES('$id', '$name', '$fp', '$fp')";
Now generally speaking you shouldn't need to insert a primary key value, just use null and it will auto increment if your table is set up that way. In your case it's not (auto_increment is not listed under "extra" for the primary key). Consider adding it.
I'll assume that the ->query() is from the PDO library, so to avoid SQL injection you should use parameter binding and your adjusted code would look like this:
$query = 'INSERT INTO names VALUES(?, ?, ?, ?)';
$stmt = $conn->prepare($query);
$stmt->execute(array($id, $name, $fp, $fp));
... or if you're using mysqli rather than PDO:
$query = 'INSERT INTO names VALUES(?, ?, ?, ?)';
$stmt = $conn->prepare($query);
$stmt->bind_param('isdd', $id, $name, $fp, $fp);
$stmt->execute();
Your query is literally inserting the string $id as you're using single quotes for your query string. Do this instead:
$query = "INSERT INTO names VALUES('$id', '$name', '$fp', '$fp')";
Just so you know the reasoning behind it, using single quotes for a string makes it so that variables are ignored.

MySQL values have a space in front?

I have a MySQL table called furniture setup like this:
| id | name | identifier |
===================================
| 1 | "? Block" | "?-block" |
| 2 |"1-Up Block" | "1-up-block" |
| 3 |"Alarm clock"|"alarm-clock" |
When I run this PHP code, the string returned is 1-up-block but with a space at the beginning of the string; the MySQL interface does not show this space. It is screwing up my programming.
$id = 2;
$fier = '';
$prep_stmt = 'SELECT identifier FROM furniture WHERE id = ?';
$stmt = $mysqli->prepare($prep_stmt);
if ($stmt) {
$stmt->bind_param('i', $id);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($identifier);
while ($stmt->fetch()) {
$fier = $identifier;
}
$stmt->close();
}
echo $fier;
Why would this space appear, and how can I get rid of it?
You could do a LIKE query for this. But Might be worth cleaning the DB and if you can adjust the script that insert this entry into the DB
SELECT name FROM furniture WHERE identifier LIKE "1-up-block"

Error in mysqli->prepare with insert statement

I'm trying to figure out why my first prepare statement works just fine but my second one doesn't. The actual INSERT INTO syntax looks correct and works when I substitute numbers and place it in a mysql console, but the prepare statement returns false.
Just to clear away the simple questions; $db_table_prefix == "uc_" and all variables are initialized. Also, the first statement sets $results == 0 (EDIT: this was my mistake, it's really 0, not 1).
global $mysqli,$db_table_prefix;
$stmt = $mysqli->prepare("SELECT COUNT(id) FROM ".$db_table_prefix."attempts WHERE ((exp_m = ?) AND (exp_n = ?) AND (max_base <= ?))");
$stmt->bind_param("iii", $m, $n, $this->max_base);
$stmt->execute();
$stmt->bind_result($results);
$stmt->fetch();
if ($results < 1)
{
$stmt = $mysqli->prepare("INSERT INTO ".$db_table_prefix."attempts (exp_m, exp_n, base_x, max_base) VALUES (?,?,?,?)");
$stmt->bind_param("iiii", $m, $n, $x, $this->max_base);
.....
}
I've included the table structure, just in case that's the issue.
mysql> describe uc_attempts;
+----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------------------+------+-----+---------+----------------+
| exp_m | bigint(20) unsigned | NO | | NULL | |
| exp_n | bigint(20) unsigned | NO | | NULL | |
| base_x | bigint(20) unsigned | YES | | NULL | |
| max_base | bigint(20) unsigned | NO | | NULL | |
| id | int(11) | NO | PRI | NULL | auto_increment |
+----------+---------------------+------+-----+---------+----------------+
I'm sure I'm just missing something simple, but after a few days of staring at the code, I needed to ask. Thanks in advance for the help. Please let me know if there is any other information I should include.
You forgot to close the first resource. I believe it can't open a second prepared statement if the first one isn't closed. I think $mysqli->prepare( ... ); will then return false and obviously false->bind_param( ... ); does not exist ;-) causing your Fatal error: Call to a member function bind_param() on a non-object-error.
global $mysqli,$db_table_prefix;
$stmt = $mysqli->prepare("SELECT COUNT(id) FROM ".$db_table_prefix."attempts WHERE ((exp_m = ?) AND (exp_n = ?) AND (max_base <= ?))");
$stmt->bind_param("iii", $m, $n, $this->max_base);
$stmt->execute();
$stmt->bind_result($results);
$stmt->fetch();
$stmt->close(); //<-- this is the problem
if ($results < 1)
{
$stmt = $mysqli->prepare("INSERT INTO ".$db_table_prefix."attempts (exp_m, exp_n, base_x, max_base) VALUES (?,?,?,?)");
$stmt->bind_param("iiii", $m, $n, $x, $this->max_base);
.....
}

Use MySQLi Prepared Statement to Enter Dynamic, Multiple Rows into Database?

I have created a HTML form where users would submit their name, email, and language skills. Since a user may speak more than one language, user will be able to generate additional rows by clicking an "add" button.
The form will then be submitted and entered into a MySQL database. I'm using two tables to hold the received data, whereas the user-id in the first table will be auto_incremented:
| (user-id) | name | email|
| user-id | language | proficiency|
Now I'm trying to write the PHP code, which looks something like this:
$name = $_POST['name'];
$email = $_POST['email'];
$add_table1 = $mysqli->prepare("INSERT INTO table1 (name, email) VALUES (?, ?)");
$add_table2 = $mysqli->prepare("INSERT INTO table2 (user_id, language, proficiency) VALUES (?, ?, ?)");
$add_table1->bind_param("ss", $name, $email);
$add_table1->execute();
$user-id = $mysqli->insert_id;
foreach($_POST['language'] as $index => $language) {
$index = intval($index);
$language = mysql_real_escape_string($language);
$proficiency = mysql_real_escape_string($_POST['proficiency'][$index]);
$add_table2->bind_param("iss", $user-id, $language, $proficiency);
$add_table2->execute();
}
$add_table1->close();
$add_table2->close();
$mysqli->close();
The table should look like this
| 1 | Mark | mark#me.com |
| 2 | Sue | sue#me.net |
|1 | English | perfect |
|1 | Spanish | awesome |
|2 | English | great |
|2 | French | ok |
|2 | Korean | fluent |
However, with my code table 1 looks fine, but table 2 looks like this
| 1 | | |
| 2 | | |
Can somebody help? Thanks!
One thing I should point out is that you don't use mysql_real_escape_string with prepared statements.
Another thing is that $user-id is not a valid variable name. You can't use a hyphen.
Edit:
It's a good thing to turn on error reporting and to output mysqli/mysqli_stmt::$error when anything fails. Most problems can be resolved with these.
Your php mysqli code looks pretty good. Are you sure you are retreiving correctly the POST values? int the foreach loop print $language and $proficiency before executing the queries

Categories