How to insert data using PDO and PHP safely? [duplicate] - php

This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 7 years ago.
I've been looking around a bit on different ways of inserting data into a database table, and I am not sure which one is the right/best/most secure way of doing it.
I have a form input in which a user can enter some data. I have the variables:
$name = "Steve";, $password = "abc123";, $ip = "1.1.1.1"; and $admin = 0;
The way I currently insert this data into the table is as following:
$q = "INSERT INTO users (username, password, ip, admin) VALUES ('$name', '$password', '$ip', '$admin')";
$query = $db->prepare($q);
$result = $query->execute();
What improvements would you make? And why? I've seen a few put :name instead of $name. But when I did that, it literally inserted ":name" into the database, and not the actual name of the person.

I don't think that's quite right still. You do want to use the :name method. The reason it inserted that literally was because you missed something on the execute, the array that tells it what values to bind to what parameters.
It should be:
$q = "INSERT INTO users (username, password, ip, admin) VALUES (:name, :password, :ip, :admin)";
$query = $db->prepare($q);
$result = $query->execute(array(":name" => $name, ":password" => $password, ":ip" => $ip, ":admin" => $admin));
As for why: It will let them handle the correct binding and sanitizing of parameters, regardless of their type.

You may use the code listed below:
$stmt = $db->prepare("INSERT INTO table(field1,field2,field3,field4,field5) VALUES(:field1,:field2,:field3,:field4,:field5)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2, ':field3' => $field3, ':field4' => $field4, ':field5' => $field5));
Full PDO reference

Related

SQLSTATE[HY093]: Invalid parameter number: parameter was not defined in PHP PDO [duplicate]

I'm getting the error "SQLSTATE[HY093]: Invalid parameter number" when I try to run the below function:
function add_persist($db, $user_id) {
$hash = md5("per11".$user_id."sist11".time());
$future = time()+(60*60*24*14);
$sql = "INSERT INTO persist (user_id, hash, expire) VALUES (:user_id, :hash, :expire) ON DUPLICATE KEY UPDATE hash=:hash";
$stm = $db->prepare($sql);
$stm->execute(array(":user_id" => $user_id, ":hash" => $hash, ":expire" => $future));
return $hash;
}
I feel like it's something simple that I'm just not catching. Any ideas?
Try:
$sql = "INSERT INTO persist (user_id, hash, expire)
VALUES (:user_id, :hash, :expire)
ON DUPLICATE KEY UPDATE hash=:hash2";
and
$stm->execute(
array(":user_id" => $user_id,
":hash" => $hash,
":expire" => $future,
":hash2" => $hash)
);
Excerpt from the documentation (http://php.net/manual/en/pdo.prepare.php):
You must include a unique parameter marker for each value you wish to pass in to the statement when you call PDOStatement::execute(). You cannot use a named parameter marker of the same name twice in a prepared statement. You cannot bind multiple values to a single named parameter in, for example, the IN() clause of an SQL statement.
This is one limitation to using PDO. PDO simply acknowledges the number of parameters in the query and the execution and throws an error on any mismatch. If you need to use parameter repetition in your queries, you have to go about it using a workaround
$sql = "insert into persist(user_id, hash, expire) values
(:user_id, :hash, :value) on duplicate key update
hash = :hash2";
$stm->execute(array(':user_id' => $user_id, ':hash' => $hash, ':hash2' => $hash,
':expire' => $expire));
You can refer to this for a more elaborate workaround - https://stackoverflow.com/a/7604080/1957346
I know this is an old question, however I think it's worth noting that a more appropriate solution would be to avoid clunky workarounds in PHP by leveraging SQL appropriately:
INSERT INTO `persist` (`user_id`, `hash`, `expire`)
VALUES (:user_id, :hash, :expire)
ON DUPLICATE KEY UPDATE `hash`=VALUES(`hash`)
This way, you only need to send the value once.
$stmt = $con->prepare("INSERT INTO items(Name, Description, Price, Country_Made, Status, Add_Date) VALUES( :zname, :zdesc, :zprice, :zcountry, zstatus, now())");
$stmt-> execute(array(
"zname" => $name,
"zdesc" => $desc,
"zprice" => $price,
"zcountry" => $country,
"zstatus" => $status
));

INSERT INTO doesn't work in php codes [duplicate]

This question already has answers here:
When to use single quotes, double quotes, and backticks in MySQL
(13 answers)
Closed 6 years ago.
I know this question is sort of dumb but I can't find out where the problem is I checked it with the codes in documentation and similar codes in stackoverflow but I can't figure out the problem.
this is my code:
if (isset($_POST['buy'])) {
$id = (int) $_POST['id'];
$name = $_POST['name'];
$price = (int) $_POST['price'];
date_default_timezone_set("Europe/London");
$date = date("Y-m-d h:i:sa");
$insquery = "INSERT INTO `purchases` (file_id, file_name, price, date) VALUES ({$id}, '{$name}', {$price}, {$date})";
$insResult = mysqli_query($con, $insquery);
if ($insResult) {
//do sth
} else {
//do sth else
}
I have tested these:
1- the post array is not empty and returns exactly those that I assigned to variables.
2- I have a table called purchases and it configured properly because I insert data in SQL and get it back successfully.
3- I have tried on SQL statement without {} around SQL variables but no luck.
and another question is after the SQL statement done how can I use the OUTPUT Inserted.ID as a variable in PHP?
thanks in advance.
date is a keyword in MySql. So use backtick (`).
INSERT INTO purchases (`file_id`, `file_name`, `price`,
`date`) ...
Instead of using direct substitution values, you could use below methods to avoid sql injection.
Using MySQLi (for MySQL):
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);
// set parameters and execute
$firstname = "John";
$lastname = "Doe";
$email = "john#example.com";
$stmt->execute();
Please refer How can I prevent SQL-injection in PHP?
Use mysqli::$insert_id for last inserted ID (Docs here)

PDO invalid parameter number mysql [duplicate]

I'm getting the error "SQLSTATE[HY093]: Invalid parameter number" when I try to run the below function:
function add_persist($db, $user_id) {
$hash = md5("per11".$user_id."sist11".time());
$future = time()+(60*60*24*14);
$sql = "INSERT INTO persist (user_id, hash, expire) VALUES (:user_id, :hash, :expire) ON DUPLICATE KEY UPDATE hash=:hash";
$stm = $db->prepare($sql);
$stm->execute(array(":user_id" => $user_id, ":hash" => $hash, ":expire" => $future));
return $hash;
}
I feel like it's something simple that I'm just not catching. Any ideas?
Try:
$sql = "INSERT INTO persist (user_id, hash, expire)
VALUES (:user_id, :hash, :expire)
ON DUPLICATE KEY UPDATE hash=:hash2";
and
$stm->execute(
array(":user_id" => $user_id,
":hash" => $hash,
":expire" => $future,
":hash2" => $hash)
);
Excerpt from the documentation (http://php.net/manual/en/pdo.prepare.php):
You must include a unique parameter marker for each value you wish to pass in to the statement when you call PDOStatement::execute(). You cannot use a named parameter marker of the same name twice in a prepared statement. You cannot bind multiple values to a single named parameter in, for example, the IN() clause of an SQL statement.
This is one limitation to using PDO. PDO simply acknowledges the number of parameters in the query and the execution and throws an error on any mismatch. If you need to use parameter repetition in your queries, you have to go about it using a workaround
$sql = "insert into persist(user_id, hash, expire) values
(:user_id, :hash, :value) on duplicate key update
hash = :hash2";
$stm->execute(array(':user_id' => $user_id, ':hash' => $hash, ':hash2' => $hash,
':expire' => $expire));
You can refer to this for a more elaborate workaround - https://stackoverflow.com/a/7604080/1957346
I know this is an old question, however I think it's worth noting that a more appropriate solution would be to avoid clunky workarounds in PHP by leveraging SQL appropriately:
INSERT INTO `persist` (`user_id`, `hash`, `expire`)
VALUES (:user_id, :hash, :expire)
ON DUPLICATE KEY UPDATE `hash`=VALUES(`hash`)
This way, you only need to send the value once.
$stmt = $con->prepare("INSERT INTO items(Name, Description, Price, Country_Made, Status, Add_Date) VALUES( :zname, :zdesc, :zprice, :zcountry, zstatus, now())");
$stmt-> execute(array(
"zname" => $name,
"zdesc" => $desc,
"zprice" => $price,
"zcountry" => $country,
"zstatus" => $status
));

INSERT INTO table VALUES - mysql_query to PDO

trying to insert values from an old mysql_query using the new PDO and can't seem to get it. Here's the old code that works with the old method:
$query = mysql_query("INSERT INTO videos VALUES ('','$title',time(),'0','$length','','$name','$cat','$reciter','$genre')");
I've tried variations of the following code taken from another question on stack, but nothing that works for me.
$query = "UPDATE people
SET price=?,
contact=?,
fname=?,
lname=?
WHERE id=? AND
username=?";
$stmt = $dbh->prepare($query);
$stmt->bindParam(1, $price);
$stmt->bindParam(2, $contact);
$stmt->bindParam(3, $fname);
$stmt->bindParam(4, $lname);
$stmt->bindParam(5, $id);
$stmt->bindParam(6, $username);
$stmt->execute();
the first value to be inserted is an auto increment value in the db. I am at a loss as to how to write that with the new PDO. Then the third is an attempt at a timestamp. All others are values that exist in the script already.
So this is more along the lines of what I'm looking for.. Its what I have now, but doesn't work.
$sql = "INSERT INTO videos (id, title, timestamp, views, length, image, vid_url, cetegory, reciter, genre)
VALUES (:id, :title, :timestamp, :views, :length, :image, :vid_url, :category, :reciter, :genre)";
$query = $DBH->prepare($sql);
$results = $query->execute(array(
":id" => '',
":title" => $title,
":timestamp" => time(),
":views" => '0',
":length" => $length,
":image" => '',
":vid_url" => $name,
":category" => $cat,
":reciter" => $reciter,
":genre" => $genre
));
If id is an autoincrement, don't pass it to your query. If you specify a value to be inserted to an autoincrement table, sql will attempt to insert that value. so don't include it in the query, let SQL do that.
Secondly, if the third field is a timestamp, set the default to
CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
SQL will update the timestamp automatically on update or insert (if you only want it on insert just put CURRENT_TIMESTAMP. then you also can drop that row.
You can also drop the images row if you aren't inserting anything there either, no point to put something in the query if you're not using it!
Also, the key PDO looks for doesn't have the colon (:) so if your item is :title, the array key will be just 'title'. So, your code should look something like:
$sql = "INSERT INTO videos ( title, views, length,, vid_url, cetegory, reciter, genre)
VALUES (:title, :views, :length, :vid_url, :category, :reciter, :genre)";
$query = $DBH->prepare($sql);
$results = $query->execute(array(
"title" => $title,
"views" => '0',
"length" => $length,
"vid_url" => $name,
"category" => $cat,
"reciter" => $reciter,
"genre" => $genre
));

PHP PDOException: "SQLSTATE[HY093]: Invalid parameter number"

I'm getting the error "SQLSTATE[HY093]: Invalid parameter number" when I try to run the below function:
function add_persist($db, $user_id) {
$hash = md5("per11".$user_id."sist11".time());
$future = time()+(60*60*24*14);
$sql = "INSERT INTO persist (user_id, hash, expire) VALUES (:user_id, :hash, :expire) ON DUPLICATE KEY UPDATE hash=:hash";
$stm = $db->prepare($sql);
$stm->execute(array(":user_id" => $user_id, ":hash" => $hash, ":expire" => $future));
return $hash;
}
I feel like it's something simple that I'm just not catching. Any ideas?
Try:
$sql = "INSERT INTO persist (user_id, hash, expire)
VALUES (:user_id, :hash, :expire)
ON DUPLICATE KEY UPDATE hash=:hash2";
and
$stm->execute(
array(":user_id" => $user_id,
":hash" => $hash,
":expire" => $future,
":hash2" => $hash)
);
Excerpt from the documentation (http://php.net/manual/en/pdo.prepare.php):
You must include a unique parameter marker for each value you wish to pass in to the statement when you call PDOStatement::execute(). You cannot use a named parameter marker of the same name twice in a prepared statement. You cannot bind multiple values to a single named parameter in, for example, the IN() clause of an SQL statement.
This is one limitation to using PDO. PDO simply acknowledges the number of parameters in the query and the execution and throws an error on any mismatch. If you need to use parameter repetition in your queries, you have to go about it using a workaround
$sql = "insert into persist(user_id, hash, expire) values
(:user_id, :hash, :value) on duplicate key update
hash = :hash2";
$stm->execute(array(':user_id' => $user_id, ':hash' => $hash, ':hash2' => $hash,
':expire' => $expire));
You can refer to this for a more elaborate workaround - https://stackoverflow.com/a/7604080/1957346
I know this is an old question, however I think it's worth noting that a more appropriate solution would be to avoid clunky workarounds in PHP by leveraging SQL appropriately:
INSERT INTO `persist` (`user_id`, `hash`, `expire`)
VALUES (:user_id, :hash, :expire)
ON DUPLICATE KEY UPDATE `hash`=VALUES(`hash`)
This way, you only need to send the value once.
$stmt = $con->prepare("INSERT INTO items(Name, Description, Price, Country_Made, Status, Add_Date) VALUES( :zname, :zdesc, :zprice, :zcountry, zstatus, now())");
$stmt-> execute(array(
"zname" => $name,
"zdesc" => $desc,
"zprice" => $price,
"zcountry" => $country,
"zstatus" => $status
));

Categories