pdo update statement using variable as table name - php

the pdo update statement below doesn't work due the table name ties to a variable. Does anyone know how to make it work?
$stmt1 = $DB_CON_C->prepare('UPDATE `".$account_list."`
SET property_type=:property_type; property_address=:property_address, property_city=:property_city, property_state=:property_state, property_zip=:property_zip WHERE contract_number=:order_list');
$stmt1->bindParam(':account_list', $account_list, PDO::PARAM_STR);
$stmt1->bindParam(':order_list', $order_list, PDO::PARAM_STR);
$stmt1->bindParam(':property_class', $property_class, PDO::PARAM_STR);
$stmt1->bindParam(':property_type', $property_type, PDO::PARAM_STR);
$stmt1->bindParam(':property_address', $property_address, PDO::PARAM_STR);
$stmt1->bindParam(':property_city', $property_city, PDO::PARAM_STR);
$stmt1->bindParam(':property_state', $property_state, PDO::PARAM_STR);
$stmt1->bindParam(':property_zip', $property_zip, PDO::PARAM_STR);
$stmt1->execute();

You will have to user single quotes in stead of double:
$stmt1 = $DB_CON_C->prepare('UPDATE `' .$account_list. '`
SET property_type=:property_type; property_address=:property_address, property_city=:property_city, property_state=:property_state, property_zip=:property_zip WHERE contract_number=:order_list');

Or, just simplify, and do:
->prepare("UPDATE {$account_list} SET...
Ie, use double quotes. The {} isn't needed, but I prefer using them because I personally use this as a prefix to the actual table name (so ("SELECT * FROM {$dbprefix}tablename"))
This way you do not need to concoct strings inside the query, which you shouldn't need to do. Just wrap the query in double quotes instead.

Related

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.

PDO execute with array returns null

I'm trying to use good PDO as always and almost everything works but one query:
$primary = 'my_id';
$table = 'my_table';
// This or...
$statement = $this->conn->prepare("SELECT MAX(:id) AS id FROM :table");
$statement->bindParam(':id', $primary, PDO::PARAM_STR);
$statement->bindParam(':table', $table, PDO::PARAM_STR);
$statement->setFetchMode(PDO::FETCH_ASSOC);
$statement->execute();
// This one. Both doesn't work.
$statement = $this->conn->prepare("SELECT MAX(:id) AS id FROM :table");
$statement->setFetchMode(PDO::FETCH_ASSOC);
$arr = array(
':id' => 'my_id',
':table' => 'my_table',
);
$statement->execute($arr);
These just return a null array. I feel so confused. So I have tried that:
$statement = $this->conn->prepare("SELECT MAX(".$primary.") AS id FROM ".$table);
$statement->setFetchMode(PDO::FETCH_ASSOC);
$statement->execute();
And it works. I feel like I'm missing something but can't figure it out. So clearly there's a problem with binding I tried different variations such as writing one of the variable manually, but no luck so far.
Thanks in advance for any help...
You can't use parameters as table names in PDO, so you will have to change this to avoid that. This is not a limitation of PDO, but a limitation of MySQL directly. The manual states that
Parameter markers can be used only where data values should appear,
not for SQL keywords, identifiers, and so forth.
Table and column names are identifiers, so using placeholders for them is not supported. See this question for an alternative method.

What the difference between bindParam and execute(array)?

$stmt = $this->_db->prepare("SELECT userid FROM users WHERE login = ? AND md5pass = ?");
#$stmt->bindParam(1, $login, PDO::PARAM_INT);
#$stmt->bindParam(2, $pass, PDO::PARAM_STR);
$stmt->execute(array($login,$pass));
$res = $stmt->fetch(PDO::FETCH_NUM);
Which way is better to transfer variables to prepeared statment bindParam or execute(array)? Both working but what is differense? Only PDO::PARAM checking? For SELECT I think array would be enough and for INSERT I sould use the bindParam. Am I right? Thanks to all. Just learning =)
With bindParam you can add the datatype and also important with bind param you are binding the variables by reference.

Crazy behaviour of PDO when executing with LIKE statement

I got code something like that:
$stmt = $pdo->prepare('SELECT * FROM table WHERE user LIKE :user');
and later I got
$stmt->bindValue(':user', '%'.$user.'%', PDO::PARAM_STR);
$stmt->execute();
And it do not work. I am pretty sure that this is correct way to do a LIKE statement with MySQL, but It not works when I enter some part of username, but when I enter full username it goes like a charm.
Any ideas why LIKE statement don't want to do a simple regex?
What I use in my own code for LIKE queries is:
$stmt = $pdo->prepare('SELECT * FROM table WHERE user LIKE CONCAT(\'%\', :user, \'%\')');
$stmt->bindValue(':user', $user, PDO::PARAM_STR);
$stmt->execute();
using the CONCAT force MySQL to generate the comparison string after the $user variable has been escaped by PDO.

Using a php variable to insert values into a mysql table

I am trying to use a variable to insert into multiple tables. When I hard code the specific table name it runs properly, when I use a variable I get a QUERY FAILEDSQLSTATE[42000]: Syntax error or access violation: 1064 error. dbname is the variable. I am using a for loop to change the name of the table. For example table 1 is budget1000, then budget 2000 etc. Here is my code
$sql='INSERT INTO ".$dbName." VALUES(:id,:category,:subCategory,
:amount, :today,:description, :year)';
try{
$st= $conn->prepare($sql);
$st->bindValue(":id", $id, PDO::PARAM_INT);
$st->bindValue(":category", $category, PDO::PARAM_INT);
$st->bindValue(":subCategory", $subCategory, PDO::PARAM_INT);
$st->bindValue(":amount", $amount, PDO::PARAM_INT);
$st->bindValue(":today", $today, PDO::PARAM_STR);
$st->bindValue(":description", $description, PDO::PARAM_STR);
$st->bindValue(":year", $year, PDO::PARAM_INT);
$st->execute();
}catch(PDOException $e ){
echo "QUERY FAILED" . $e->getMessage();
}
It looks like there's a quote mismatch, you start off with single quotes but then switch to double quotes when you concatenate the DB name into your string. Try replacing the single quotes at the beginning and end of your $sql string with double quotes and remove the periods around $dbname, or use single quotes all the way through.
Try this instead:
$sql='INSERT INTO '.$dbName.' VALUES(:id,:category,:subCategory,:amount, :today,:description, :year)';

Categories