Prepared Statements with PDO doesn't work - php

I did some research around and I found two ways to prepared my statements from PDO object. But it seems like both are not working at all. I am missing something?
Named placeholders
$email = 'my_email';
$code = 'my_private_code';
$pdo = new PDO('mysql:host=personal_info;dbname=personal_info', 'personal_info', 'personal_info');
$sql = "UPDATE `promo` SET code = :code WHERE email = :email";
$st = $pdo->prepare($sql);
$st->execute(array(
':code' => $code,
':email' => $email
));
Unamed placeholders
$pdo = new PDO('mysql:host=personal_info;dbname=personal_info', 'personal_info', 'personal_info');
$st = $pdo->prepare("INSERT INTO promo (`email`, `code`) VALUES (?, ?)");
$st->bindParam(1, $email);
$st->bindParam(2, $code);
$email = 'my_email#hotmail.com';
$code = 'my_private_code';
$st->execute();

Related

PDO MYSQL Prepared Update Statement using PHP Not executing

I am trying to execute a prepared statement using a PDO via PHP on a MySQL database.
I have tried two versions of the code both have not worked. The function update will execute but nothing will get updated in the database. My view customerData functions using fetch() and fetchAll() both work as does my deleteData function.
My current database structure is:
customerID(int11)
firstName(varchar(50)
lastName(varchar(50)
address(varchar(50)
city(varchar(50)
state(varchar(50)
postalCode(varchar(20)
countryCode(char(2)
phone(varchar(20)
email(varchar(50)
password(varchar(20)
The current version of code I am using:
function update_customer($customerID, $firstName, $lastName, $address, $city, $state, $postalCode, $countryCode, $phone, $email, $password)
{
global $db;
$query = "UPDATE customers
SET
firstName = :first,
lastName = :last,
address = :add,
city = :c,
state = :s,
postalCode = :postal,
countryCode = :country,
phone = :p,
email = :e,
password = :password
WHERE customerID = :ID";
$statement = $db->prepare($query);
$statement->bindValue(':first',$firstName);
$statement->bindValue(':last', $lastName);
$statement->bindValue(':add', $address);
$statement->bindValue(':c' ,$city);
$statement->bindValue(':s',$state);
$statement->bindValue(':postal', $postalCode);
$statement->bindValue(':country',$countryCode);
$statement->bindValue(':p', $phone);
$statement->bindValue(':e', $email);
$statement->bindValue(':pass', $password);
$statement->bindValue(':ID', $customerID);
$statement->execute();
$statement->closeCursor();
}
The other version of code I have used
function update_customer($customerID, $firstName, $lastName, $address, $city, $state, $postalCode, $countryCode, $phone, $email, $password)
{
global $db;
$query = "UPDATE customers
SET
firstName = ?,
lastName = ?
address = ?,
city = ?,
state = ?,
postalCode = ?,
countryCode = ?,
phone = ?,
email = ?,
password = ?
WHERE customerID = ?";
$statement = $db->prepare($query);
$statement->bindParam('ssssssssssi', $firstName, $lastName, $address, $city, $state, $postalCode, $countryCode, $phone, $email, $password, $customerID);
$statement->execute();
$statement->closeCursor();
}
My other 3 prepared statements work perfectly, for example here is the prepared statement that populates the update customer form.
function view_customerData ($customerID) {
global $db;
$query = "SELECT * FROM customers
WHERE customerID = $customerID";
try {
$statement = $db->prepare($query);
$statement->execute();
$customerData = $statement->fetch();
return $customerData;
} catch (PDOException $e) {
$error_message = $e->getMessage();
echo "<p>Database error: $error_message </p>";
exit();
}
}
Try to put the whole update customer code on try block and put catch block if any error occurs. But first of all fix this line
$statement->bindValue(':pass', $password);
to
$statement->bindValue(':password', $password);
^^^^
try {
//.....put your update customer code here ...
} catch (PDOException $e) {
$error_message = $e->getMessage();
echo "<p>Database error: $error_message </p>";
exit();
}

PDO parameterized query code review, how safe am i?

I'm a PHP newbie that just starts to code. Before coding any further, I need to know if I already on the right path on making a secure web. So please review my code samples below.
PHP Version 5.4.34
Database Server version: 5.5.40-cll - MySQL Community Server (GPL)
on connection.php
//should I use utf8mb4 and set server connection collation to utf8mb4_general_ci?
//also on html, is including <meta charset="utf-8"> necessary?
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8');
$db = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8", $username, $password, $options);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); // enabled by default?
select query
$query = "SELECT * FROM tbname WHERE username = :username";
$params = array(':username' => $_POST['username']);
try
{
$stmt = $db->prepare($query);
$result = $stmt->execute($params);
}
catch(PDOException $ex)
{
die();
}
insert query
$query = "INSERT INTO log (
username,
email,
ip,
time
) VALUES (
:username,
:email,
:lastip,
:lastlog
)";
$params = array(
':username' => $_POST['username'],
':email' => $_POST['email'],
':lastip' => $_SERVER['REMOTE_ADDR'],
':lastlog' => time()
);
try
{
$stmt = $db->prepare($query);
$result = $stmt->execute($params);
}
catch(PDOException $ex)
{
die();
}
update query
$params = array(
':username' => $_SESSION['userdata']['username'],
':email' => $_POST['email'],
':age' => $_POST['age'],
':gender' => $_POST['gender']
);
$query = "UPDATE users SET
email = :email,
age = :age,
gender = :gender
where username = :username";
try
{
$stmt = $db->prepare($query);
$result = $stmt->execute($params);
}
catch(PDOException $ex)
{
die();
}
How safe am i from SQL injection? Safe enough from 2nd order attack?
Totally safe. The PDO Statement prepares the query to avoid SQL injections. Even if they try, the prepare() function make the necessary changes before send to the database.

php PDO prepare(" INSERT ..(variables ) VALUES(?,?,) produces an error need assistance

$query = $this->link->prepare("INSERT INTO surveys (`username`,`inspected`,
`comments`,`ip_address`,`date`,`time`)
VALUES '(?,?,?,?,?,?)';);
$values = array ($username,$inspected,$comments,$ip_address,$date,$time);
var_dump($query);$rowCount = $query->rowCount();
$return $rowCount;
You can base yourself on the following which I've prepared for you.
Sidenote: I'm not entirely sure as to why you want to use rowCount() for, so I left it out for now.
If you're looking to check if a record exists using rowCount(), let me know.
The following method works to insert data into a database, which is based on a method I use.
<?php
$dbname = 'xxx';
$username = 'xxx';
$password = 'xxx';
try {
$pdo = new PDO("mysql:host=localhost;dbname=$dbname", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
exit( $e->getMessage() );
}
$sql = "INSERT INTO surveys (
username,
inspected,
comments,
ip_address,
date,
time
) VALUES (
:username,
:inspected,
:comments,
:ip_address,
:date,
:time)";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':username', $_POST['username'], PDO::PARAM_STR);
$stmt->bindParam(':inspected', $_POST['inspected'], PDO::PARAM_STR);
$stmt->bindParam(':comments', $_POST['comments'], PDO::PARAM_STR);
$stmt->bindParam(':ip_address', $_POST['ip_address'], PDO::PARAM_STR);
$stmt->bindParam(':date', $_POST['date'], PDO::PARAM_STR);
$stmt->bindParam(':time', $_POST['time'], PDO::PARAM_STR);
// $stmt->execute();
$stmt->execute(array(':username' => $_POST['username'],':inspected' => $_POST['inspected'],':comments' => $_POST['comments'],
':ip_address' => $_POST['ip_address'],':date' => $_POST['date'],':time' => $_POST['time']));
if($stmt != false) {
echo "success!";
} else {
echo "an error occured saving your data!";
}

MySQL prepared statement returns false

I have the following working MySQL insert:
$tableSelect = $_POST["tableSelect"];
$companyName = $_POST["companyName"];
$telephone = $_POST["telephone"];
$fax = $_POST["fax"];
$email = $_POST["email"];
$address = $_POST["address"];
$postcode = $_POST["postcode"];
$category = $_POST["category"];
$contact = $_POST["contact"];
$contactTel = $_POST["contactTel"];
$contactEmail = $_POST["contactEmail"];
$sql = "INSERT INTO $tableSelect (companyName,telephone,fax,email,address,postcode,category,contact,contactTel,
contactEmail) VALUES ('$companyName','$telephone','$fax','$email','$address','$postcode','$category',
'$contact','$contactTel','$contactEmail');";
if (!mysqli_query($con,$sql)) {
die('Error: ' . mysqli_error($con));
}
However, I've tried to change this into a prepared statement to protect myself from injection, like so:
$stmt = $con->prepare("INSERT INTO suppliers (companyName,telephone,fax,email,address,postcode,
category,contact,contactTel,contactEmail) VALUES(:companyName, :telephone, :fax, :email, :address,
:postcode, :category, :contact, :contactTel, :contactEmail);");
if ($stmt !== FALSE) {
$stmt->bindParam(':companyName',$companyName);
$stmt->bindParam(':telephone',$telephone);
$stmt->bindParam(':fax',$fax);
$stmt->bindParam(':email',$email);
$stmt->bindParam(':address',$address);
$stmt->bindParam(':postcode',$postcode);
$stmt->bindParam(':category',$category);
$stmt->bindParam(':contact',$contact);
$stmt->bindParam(':contactTel',$contactTel);
$stmt->bindParam(':contactEmail',$contactEmail);
$companyName = $_POST["companyName"];
$telephone = $_POST["telephone"];
$fax = $_POST["fax"];
$email = $_POST["email"];
$address = $_POST["address"];
$postcode = $_POST["postcode"];
$category = $_POST["category"];
$contact = $_POST["contact"];
$contactTel = $_POST["contactTel"];
$contactEmail = $_POST["contactEmail"];
$stmt->execute();
}
else {
echo "Could not connect";
}
Every time I run it, $stmt returns false. It's the first time I've used prepared statements and I'm fairly new to MySQL so some pointers would be greatly appreciated.
The syntax for mysqli is wrong. You have tried using PDO. For mysqli
$stmt = $con->prepare("INSERT INTO suppliers (companyName,telephone,fax,email,address,postcode,category,contact,contactTel,contactEmail) VALUES(?,?,?,?,?,?,?,?,?,?)");
if($stmt){
$stmt->bind_param('ssssssssss',$companyName,$telephone,$fax,$email,$address,$postcode,$category,$contact,$contactTel,$contactEmail);
//s for string, i for integer, d for double, b for blob
$stmt->execute();
}else{
echo($con->error); //TO display Error
}
Though your question is a sure offtopic, here are some pointers
Assuming you are using PDO for the second example (for some reason you didn't indicate it in your question)
you have to tell PDO to throw exceptions
$con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
it will let you to at least have an error message to think of.
a table name should never be supplied by client side.
adjust your bound variables to make them fit the query
Instead of that long and windy code just remove unnecessary members from $_POST array and pass it to execute
something like this
$con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$sql = "INSERT INTO suppliers
(companyName,telephone,fax,email,address,postcode,
category,contact,contactTel,contactEmail)
VALUES
(:companyName, :telephone, :fax, :email, :address,
:postcode, :category, :contact, :contactTel, :contactEmail)";
$stmt = $con->prepare($sql);
unset ($_POST['submit']);
// make sure you unset all the useless members
$stmt->execute($_POST);

PHP changing old mysql_query to PDO

I have some old mysql_query queries in my code which i want to convert in to PDO but am struggling to get to work.
my original code was:
mysql_query("UPDATE people SET price='$price', contact='$contact', fname='$fname', lname='$lname' WHERE id='$id' AND username='$username' ")
or die(mysql_error());
now i am trying:
$sql = "UPDATE people SET price='$price', contact='$contact', fname='$fname', lname='$lname' WHERE id='$id' AND username='$username'";
$q = $conn->query($sql) or die("failed!");
but can't seem to get it to work, any ideas?
UPDATED CODE:
$conn = new PDO("mysql:host=$host;dbname=$db",$user,$pass);
// check if the form has been submitted. If it has, process the form and save it to the database
if (isset($_POST['submit']))
{
// confirm that the 'id' value is a valid integer before getting the form data
if (is_numeric($_POST['id']))
{
// get form data, making sure it is valid
$id = $_POST['id'];
$fname = mysql_real_escape_string(htmlspecialchars($_POST['fname']));
$lname = mysql_real_escape_string(htmlspecialchars($_POST['lname']));
$contact = mysql_real_escape_string(htmlspecialchars($_POST['contact']));
$price = mysql_real_escape_string(htmlspecialchars($_POST['price']));
// check that firstname/lastname fields are both filled in
if ($fname == '' || $lname == '' || $contact == '' || $price == '' )
{
// generate error message
$error = 'ERROR: Please fill in all required fields!';
//error, display form
renderForm($id, $fname, $lname, $contact, $price, $error);
}
else
{
// save the data to the database
$username = $_SESSION['username'];
$query = "UPDATE people
SET price=?,
contact=?,
fname=?,
lname=?
WHERE id=? AND
username=?";
$stmt = $db->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();
// once saved, redirect back to the view page
header("Location: view.php");
}
For more information visit this link: PHP PDO
based on your example,
<?php
$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();
?>
PDO Prepared statements and stored procedures
Note that when working with the mysql driver for PDO you always have to disable emulated prepared statements:
$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');
$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = 'UPDATE people SET';
$sql.= ' price = :price,';
$sql.= ' contact = :contact,';
$sql.= ' fname = :fname,';
$sq;.= ' lname = :lname';
$sql.= ' WHERE id= :id AND username = :username';
$stmt = $pdo->prepare($sql);
$stmt->execute(array(
':price' => $price,
':contact' => $contact,
':fname' => $fname,
':lname' => $lname,
':id' => $id,
':username' => $username,
));
As you can see I have used named parameters, because when you have lots of them it is imho way clearer what you are doing.
Note: that ircmaxell is currently working on getting the default to always use real prepared statements, but until that (which may take some while) you always have to disable them for mysql.
If you're going to use PDO, you need to look at prepare() and execute otherwise you're losing the security that PDO is offering and retaining the SQL Injections. So, given your example:
$conn = new PDO(/*connection info*/);
$query = $conn->prepare("UPDATE people "
. "SET price = :price, "
. " contact = :contact, "
. " fname = :fname, "
. " lname = :lname "
. "WHERE id = :id "
. " AND username = :username");
$result = $query->execute(array(
':price' => $price,
':contact' => $contact,
':fname' => $fname,
':lname' => $lname,
':id' => $id,
':username' => $username
));
That's more the lax way, but you can also bindParam and be explicit as to the data type it's expecting.
Few things you have to be clear while using PDO extension is that there are multiple ways to get things done.
The way you are currently using being one of them including few more. However it is always a good idea to bind parameters separately, because this prevents many problems like SQL Injection and many more.
Other important things to look at are statement, prepare and execute.
$conn = new PDO("...."); //Creating the handler
//Create the statement
$stmt = $conn -> prepare("UPDATE people SET price = :price, contact = :contact, fname = :fname, lname = :lname WHERE id= :id AND username = :username");
// Bind the params
$stml -> bindParam(":contact", $contact, PDO::PARAM_STR); //This way you can also define the DATATYPE of the parameter
//Execute
$stmt -> execute(array(
":price" => $price, //another way of binding the params
":fname" => $fname,
":lname" => $lname,
":id" => $id,
":username" => $username));

Categories