PDO and alphanumeric strings? - php

The current error when running this from the command line is "Call to a member function bindParam() on a non-object" which I've worked out to being a problem with the variable $orderPO. Something does not like non-numeric characters which led me to the bindParam PARAM_STR business which does not work either. The database fields are both varchar 50.
My search skills are failing me. I know this must be posted somewhere about a million times but I can't seem to find it. I am completely open to doing this another way if someone has a better idea.
Current attempt code:
try
{
$orderNum = '123456';
$orderPO = '123456-A';
$dbh = new PDO("mysql:host=localhost;dbname=dbname", 'someuser', 'somepass');
$stm = $dbh->prepare("insert into some_table (order_number, order_po)");
$stm->bindParam(':order_number', $orderNum, PDO::PARAM_STR);
$stm->bindParam(':order_po', $orderPO, PDO::PARAM_STR);
$stm->execute();
print_r($stm);
print_r($dbh);
$arr = $stm->errorInfo();
print_r($arr);
$stm->closeCursor();
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}

In order to bind parameters using PDO, you will need to use placeholders, like this:
$stm = $dbh->prepare("
INSERT INTO `some_table` SET
`order_number` = :order_number,
`order_po` = :order_po
");
$stm->bindParam(':order_number', $orderNum, PDO::PARAM_STR);
$stm->bindParam(':order_po', $orderPO, PDO::PARAM_STR);
Notice the inclusion of the : character before the named placeholder. I also added column names to your query.
Read further and see examples: PDO bindParam

The correct syntax is
$stm = $dbh->prepare("insert into some_table (order_number, order_po) VALUES (?, ?)");
$stm->bindParam(1,$orderNum);
$stm->bindParam(2,$orderPO);
include the questions marks, the numbers in the bindParam call refer to which question mark you're binding the parameter to

You are trying to use bindparam, but bind param matches ? not cursors :. You have not included any parameters or values.
Also, you are missing your VALUES statement within the query, which is causing the query to fail. This is why you get the "Call to a member function bindParam() on a non-object"
To use the :value syntax, use bindValue, not bindParam. to use bindParam, switch the :value to ? in your query and number them in order is your execute array.
try
{
$orderNum = '123456';
$orderPO = '123456-A';
$dbh = new PDO("mysql:host=localhost;dbname=dbname", 'someuser', 'somepass');
$stm = $dbh->prepare("insert into some_table (order_number, order_po) VALUES (:order_number, :order_po)");
$stm->bindvalue(':order_number', $orderNum, PDO::PARAM_STR);
$stm->bindvalue(':order_po', $orderPO, PDO::PARAM_STR);
$stm->execute();
print_r($stm);
print_r($dbh);
$arr = $stm->errorInfo();
print_r($arr);
$stm->closeCursor();
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}

Related

Postgresql not binding in prepared statement for SELECT in PHP

<?php
try
{
global $db;
$user = 'postgres';
$password = '*****'; //For security
$db = new PDO('pgsql:host=localhost;dbname=dnd', $user, $password);
$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
}
catch (PDOException $ex)
{
echo 'ERROR!!: ' . $ex->getMessage();
die();
}
$table = htmlspecialchars($_REQUEST['table']);
$idNum = htmlspecialchars($_REQUEST['id']);
try {
//$query = "SELECT * FROM $table WHERE id = $idNum"; This works
//$query = "SELECT * FROM $table WHERE id = :number"; This works
$query = "SELECT * FROM :tableName WHERE id = :number";
$statement = $db->prepare($query);
$statement->bindValue(":tableName", $table, PDO::PARAM_STR);
$statement->bindValue(":number", $idNum, PDO::PARAM_INT);
$statement->execute();
$info = $statement->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $excep) {
echo "Opps: " . $excep->getMessage();
die();
}
Okay I'm going crazy here trying to get this to work.
I have a database set up that I need to query from. I receive the query from an AJAX request with the name of the table I want and the id for the item. When I try to query with both variables, the binding does not occur in the prepared statement and instead I get this error code
Opps: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "$1" LINE 1: SELECT * FROM $1 WHERE id = 1 ^
When I have just the straight PHP variables it works fine so I know it can work, but when I want to bind multiple it seems to fail and give a variable number as above.
I can also get it to work if I simply have one of the variables bound, such as the second commented out query in the code - this only works tho if I have the variable I want at the end and not if I wanted to lookup the table spot. (I.E.
$query = "SELECT * FROM :tableName WHERE id = $idNum"; does not work)
I need to cleanse the variables to prevent SQL injection, but I can't do that without binding the variables in a prepared statement. Any help would be appreciated!
According to the PHP manual you can't bind a tablename. As you mentioned it, you can replace it by a variable, but you can't replace it with a placeholder.
So the only solution that will work for you is the query you have above:
$query = "SELECT * FROM $table WHERE id = :number"
This will be what you're looking for. If you want to make it safe for injection, you have to find another way. (Regex for example).
Ref: http://us3.php.net/manual/en/book.pdo.php#69304

PHP SQL prepared select query not returning anything

When I run the code below, it returns nothing. When I explicitly type a string in the place of the '?', it will return the expected result but using the prepared version has not worked for me thus far. I do not believe there is any kind of versioning issue as using prepared statements for INSERT queries has worked for me in the past. What might be the problem here with the prepared statement?
$pdo = new PDO("mysql:host=localhost;dbname=database", $user, $pass);
$sql = "SELECT * FROM table WHERE column LIKE '%?%';";
$stmt = $pdo->prepare($sql);
$stmt->execute(array($_GET['searchterm']));
$results = $stmt->fetchAll();
print_r($results);
You are preparing the value so it isn't behaving as if you just put the string inside of the query.
When preparing a string you don't need to add " or ', that is done for you. You need to add the %'s into the value that you are escaping.
$pdo = new PDO("mysql:host=localhost;dbname=database", $user, $pass);
$sql = "SELECT * FROM table WHERE column LIKE ?;";
$stmt = $pdo->prepare($sql);
$stmt->execute(array("%{$_GET['searchterm']}%"));
$results = $stmt->fetchAll();
print_r($results);

Which PDO bind approach should be used for greater security?

I know of two ways to use PDO in PHP to update a MySQL database record. Please could someone explain which one I should use for better security and the difference and I am a little confused.
Method One:
$user = "root";
$pass = "";
$dbh = new PDO('mysql:host=somehost;dbname=somedb', $user, $pass);
$sql = "UPDATE coupons SET
coupon_code = :coupon_code,
valid_from = :valid_from,
valid_to = :valid_to,
discount_percentage = :discount_percentage,
discount_amount = :discount_amount,
calculationType = :calculationType,
limit = :limit
WHERE coupon_code = :coupon";
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':coupon_code', $_POST['coupon_code'], PDO::PARAM_STR);
$stmt->bindParam(':valid_from', $_POST['$valid_from'], PDO::PARAM_STR);
$stmt->bindParam(':valid_to', $_POST['valid_to'], PDO::PARAM_STR);
$stmt->bindParam(':discount_percentage', $_POST['discount_percentage'], PDO::PARAM_STR);
$stmt->bindParam(':discount_amount', $_POST['discount_amount'], PDO::PARAM_STR);
$stmt->bindParam(':calculationType', $_POST['calculationType'], PDO::PARAM_STR);
$stmt->bindParam(':limit', $_POST['limit'], PDO::PARAM_STR);
$stmt->bindParam(':coupon', $_POST['coupon_code'], PDO::PARAM_STR);
$stmt->execute();
Method Two:
$dbtype="somedbtype";
$dbhost="somehost";
$dbname="somedb";
$dbuser="someuser";
$dbpass= "somepass";
$conn = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass);
$title = 'PHP Pattern';
$author = 'Imanda';
$id = 3;
$sql = "UPDATE books
SET title=?, author=?
WHERE id=?";
$q = $conn->prepare($sql);
$q->execute(array($title,$author,$id));
From what I can see, method two does not bind the data, rather insert it directly into the query as an array type. Does this make the script more susceptible to SQL injection or other security risks?
The only difference between the two is that if you pass the array in to the execute function rather than calling bindParam yourself, it treats all parameters as PDO::PARAM_STR automatically, whereas in calling bindParam yourself you could bind them as integers, etc.
From the docs:
input_parameters
An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as PDO::PARAM_STR.
You can also see from the examples there that you can use named parameters (e.g. :limit) when passing the array into the execute function. You don't have to just put ?. In that case you give the array a key:
$sth->execute(array(':calories' => $calories, ':colour' => $colour));
It's mostly a matter of preference. Both protect you from injection.
Though I think it's much easier to force data type with bind(), where as using execute(array()) will be using strings.

First run with PDO getting a Call to a member function bindParam() on a non-object error

This is my first run with PDO, not sure how much better it is than using mysqli but its part of a project I have to create.
Here is the code that is causing the message, all I am trying to do is update pieces of data within my db table.
<?php
//PHP Data Objects
try{
//Connect
$dbh = new PDO('mysql:host=localhost; dbname = company; charset=utf-8','root', 'bachi619');
} catch(PDOException $e){
echo $e->getMessage();
}
$id = 4;
$name = "logan";
$department = "Design";
$sth = $dbh->query("UPDATE employees SET department=:department,last_name=:lastname WHERE id=:id");
//bind
$sth->bindParam(':id',$id);
$sth->bindParam(':lastname',$name);
$sth->bindParam(':department',$department);
$sth->execute();
?>
you have to use
$dbh -> prepare("UPDATE employees SET department=:department,last_name=:lastname WHERE id=:id");
Use prepare for PDO, check this http://in3.php.net/manual/en/pdostatement.bindparam.php
$sth = $dbh->prepare('UPDATE employees SET department=:department,last_name=:lastname WHERE id=:id' );
The dsn should be non spaced
$dbh = new PDO('mysql:host=localhost;dbname=company','root', 'bachi619');
You need to prepare the SQL statement like this
$sth = $dbh->prepare( 'UPDATE employees SET department=:department,last_name=:lastname WHERE id=:id' );
Then bind the parameters
$sth->bindParam(':id',$id);
$sth->bindParam(':lastname',$name);
$sth->bindParam(':department',$department);
and finally execute the query
$sth->execute();

PDO bindParam() with prepared statement isn't working

Ok, this is the problem:
This works:
$STH = $DBH->prepare("SELECT * FROM juegos WHERE id = 1");
$STH->execute();
This doesn't:
$STH = $DBH->prepare("SELECT * FROM juegos WHERE id = :id");
$STH->bindParam(':id', '1', PDO::PARAM_STR);
$STH->execute();
What in the world am I doing wrong? It doesn't even throw an exception
Thank you everyone!
Also, this is the whole code
<?php
try {
$DBH = new PDO("everything is", "ok", "here");
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$STH = $DBH->prepare("SELECT * FROM juegos WHERE id = :id");
$STH->bindParam(':id', '1', PDO::PARAM_STR);
$STH->execute();
$STH->setFetchMode(PDO::FETCH_ASSOC);
while($row = $STH->fetch()) {
echo $row['nombre']."<br/>";
}
$DBH = null;
echo "Todo saliĆ³ bien";
} catch (PDOException $e) {
echo "Error";
}
?>
Using bindParam() the variable is bound as a reference.
A string can't be passed by reference.
The following things can be passed by reference:
Variables, i.e. foo($a)
New statements, i.e. foo(new foobar())
References returned from functions
Try using bindValue()
$STH->bindValue(':id', '1', PDO::PARAM_STR);
PHP bindParam() binds a PHP variable to a corresponding named or question mark placeholder in the SQL statement that was used to prepare the statement.
The correct way to use bindParam is:
$id = 1;
$sth = $DBH->prepare("SELECT * FROM juegos WHERE id = :id");
$sth->bindParam(':id', $id, PDO::PARAM_INT);// use bindParam to bind the variable
// ^ PDO::PARAM_INT - the value of the variable $id should be an int
// ^ $id - the variable being represented by ':id',
// ^ :id - represents the variable
// $id - the variable being represented by ':id',
PHP bindValue() binds a value to a corresponding named or question mark placeholder in the SQL statement that was used to prepare the statement.
$id=10;
$name=roadkill;
$sth = $dbh->prepare('SELECT *
FROM juegos
WHERE id < :id AND name = :name');
$sth->bindValue(':id', $id, PDO::PARAM_INT);// use bindValue to bind the variable's value
$sth->bindValue(':name', $name, PDO::PARAM_STR);// use bindValue to bind the variable's value
The key difference between these two methods is that unlike PDOStatement::bindValue(), with bindParam() the variable is bound as a reference and will only be evaluated at the time that PDOStatement::execute() is called.
The value for the :tabla parameter will be automatically quoted and escaped by PDO. The query executed would become:
SELECT * FROM 'juegos'
which is not valid SQL.
do not pass the value directly to BindParam.
try {
// $DBH = new PDO("everything is", "ok", "here");
$DBH = new PDO("mysql:host=localhost;dbname=test", 'root', '');
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$STH = $DBH->prepare("SELECT * FROM statstracker WHERE SrNo = :id");
$id = 1; // here you should keep it as variable and pass it to param
$STH->bindParam(':id', $id, PDO::PARAM_STR);
$STH->execute();
$STH->setFetchMode(PDO::FETCH_ASSOC);
while($row = $STH->fetch()) {
echo $row['SrNo']."<br/>";
}
$DBH = null;
echo "Todo saliĆ³ bien";
} catch (PDOException $e) {
echo "Error";
}
For me replacing the double quote by single quote fixed the issue.
Previous:
$STH = $DBH->prepare("SELECT * FROM statstracker WHERE SrNo = :id");
Solution:
$STH = $DBH->prepare('SELECT * FROM statstracker WHERE SrNo = :id');
And it works, though not sure why.
Hope it helps!

Categories