Can I use name of the column as parameter in PDO? - php

I'm trying to execute this:
$colparam = 'abcd';
$stmt = $db->prepare("SELECT DISTINCT ? AS kol FROM katalog ORDER BY kol ASC");
$stmt->execute(array($colparam));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
and it's not working (no errors, just empty array as result).
Instead this works fine:
$stmt = $db->prepare("SELECT DISTINCT abcd AS kol FROM katalog ORDER BY kol ASC");
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
So is there any catch with the use of parameter as a name of the column in PDO?

No, you can't use parameter replacements for any database objects (tables, columns, etc.) in MySQL.
When you think about what a prepared statement actually is, this makes complete sense. As how can MySQL prepare a query execution plan when it does not even know the database objects involved.
I certainly wish that more documentation would actually cover what a prepared statement actually does (beyond it's obvious use for parametrization).
Here is link to MySQL prepared statement documentation for more reading:
https://dev.mysql.com/doc/refman/5.6/en/sql-syntax-prepared-statements.html

Related

PDO adds the apostrophe to the mySQL query

After years of reading it's time to ask first question :)
My problem is that after migrating the code from mySQLi to PDO we have got a problem as it seems PDO adds the apostrophes to the query.
PHP code goes like that:
$sort = $_GET['sort']; << table column name (mySQL VARCHAR only columns)
....
$query = 'SELECT * FROM table WHERE xxx > 0';
$query .= ' ORDER BY :sort ASC ;';
$qry_result= $db->prepare($query);
$qry_result->execute(array(':sort'=>$sort));
mysqli version went smoothly but now queries (mysql log file) looks like this:
SELECT * FROM table where xxx > 0 ORDER BY 'SORT_VAR_VALUE' ASC;
^ 2 problems ^
So the table is NOT sorted, as sort order (from mySQL point of view) is wrong.
phpinfo() does not get any results for search on "magic" nor "quotes" btw.
Any idea ??
The placeholders in PDO statements are for values only. If you want to add actual SQL to the query you need to do it another way.
First, you should sanitize $sort and surround it with backticks in the query.
$sort = preg_replace('/^[a-zA-Z0-9_]/', '', $sort);
Then you could double quote the query string and PHP will replace $sort with it's value for you:
$query = "SELECT * FROM table WHERE xxx > 0 ORDER BY `$sort` ASC";
Or you could replace it with preg_replace like so:
$query = 'SELECT * FROM table WHERE xxx > 0 ORDER BY `:sort` ASC';
$query = preg_replace('/:sort/', $sort, $query, 1);
I would use the preg_replace method because it allows you to reuse the query if you assign the results from preg_replace to another variable instead of overwriting the original variable.
by default pdo binds values as strings.
To fix this you will want to check that the column is actually a valid name and then add it to the query, you can do it the following way:
function validName($string){
return !preg_match("/[^a-zA-Z0-9\$_\.]/i", $string);
}
if(validName($sort)){
$db->prepare("SELECT * FROM table where xxx > 0 ORDER BY $sort ASC");
}
With PDO it's not possible to bind other things that variables in the WHERE statement. So you have to hard code the names of the columns you order by.
See How do I set ORDER BY params using prepared PDO statement?
or Can PHP PDO Statements accept the table or column name as parameter? for further explanations.

Is it possible to use SELECT * in prepared statement?

Is it possible to use * in query for $stmt->prepare() and using bind_result()?
For example I have to select 50 columns in 1 table with conditions as parameter, and if I type all 50 columns it will take time.
So in this scenario how can I get the result?
$stmt->prepare("Select * from table where col1 = ? and col2=? and col3=? and col4=?")
$stmt->bind_param("ssss",$col1, $col2, $col3, $col4)
$stmt->execute()
Yes, of course.
Just use $res = $stmt->get_result() followed by familiar $row = $res->fetch_assoc() stuff
However, for a newbie, you are indeed strictly advised to choose PDO over mysqli.
Only the question mark is used as a placeholder character by mysqli, so you can use * just as you usually would.
To save time, if you are using PDO, you can name your parameters and then mass assign them.
E.g.
$sql = 'SELECT *
FROM table
WHERE col1=:myval OR col2=:myval OR col3=:myval';
$sth = $dbh->prepare($sql);
$sth->execute(array(':myval ' => 150));
$red = $sth->fetchAll();

Using PDO in PHP to count all from database and the 'WHERE' is a variable that has to be cleaned

I'm trying to count all of the rows from an item list where the id matches a user input. I am switching all of my code from mysql to PDO as I have learned it is much better.
The code below is what I found to work in my situation.
$id = '0';
$sql="SELECT count(*) FROM item_list WHERE item_id = $id";
$data=$connMembers->query($sql)->fetchcolumn();
echo $data;
However, It is not safe for a live site due to sql injections.
I want to know how can I change it to work whare it sanatizes the user input.
I would prefer using a prepare and execute functions so the variables are kept seperately.
So is there something I can do?
This is where you start binding parameters. I prefer to do it using ? and one array for inputs.
Assuming $connMembers is your PDO object:
$sql="SELECT COUNT(*) FROM item_list WHERE item_id = ?";
$input=array($id); //Input for execute should always be an array
$statement=$connMembers->prepare($sql);
$statement->execute($input);
$data=$statement->fetchObject();
var_dump($data);
To add more variables to your sql, just add another ? to the query and add the variable to your input.
$sql="SELECT COUNT(*) FROM item_list WHERE item_id = ? AND item_name=?";
$input=array($id, $name); //Input for execute should always be an array
$statement=$connMembers->prepare($sql);
$statement->execute($input);
$data=$statement->fetchObject();
var_dump($data);
OR you can use bindParam:
$sql="SELECT COUNT(*) FROM item_list WHERE item_id = :itemID";
$statement=$connMembers->prepare($sql);
$statement->bindParam(':itemID', $id);
/*Here I am binding parameters instead of passing
an array parameter to the execute() */
$statement->execute();
$data=$statement->fetchObject();
var_dump($data);

Securing PHP MySQL code

I have a PHP search suggestion script which uses MySQL as its back-end. I am aware there are many vunerabilities in my code, I was just wondering what I can do to make it more secure.
Here is my code:
<?php
$database=new mysqli('localhost','username','password','database');
if(isset($_POST['query'])){
$query=$database->real_escape_string($_POST['query']);
if(strlen($query)>0){
$suggestions=$database->query(
"SELECT * FROM search WHERE name LIKE '%" . $query .
"%' ORDER BY value DESC LIMIT 5");
if($suggestions){
while($result=$suggestions->fetch_object()){
echo '<a>'.$result->name.'</a>';
}
}
}
}
?>
Actually there aren't, considering you are escaping the only external value in the SQL
Anyway I suggest you to use PDO::prepare for queries. Go here for further infos
http://it.php.net/manual/en/pdo.prepare.php
Example:
$sth = $dbh->prepare('SELECT * FROM article WHERE id = ?');
$sth->execute(array(1));
$red = $sth->fetchAll();
Some tips from me:
use PDO,
don't concatenate query parameters, use prepared statements in PDO,
don't put "*" in SELECT statement, get only the columns you'll need,
use fetchAll() in PDO, don't fetch records in while() loop.

How to create a prepared statement in PHP with a formula involving columns in the where clause?

I want to create prepared stmt such as
"SELECT id,latitude,longitude
FROM sometable WHERE
(3437.74677 * ACOS(SIN(latitude_radians) * SIN(?) +
COS(latitude_radians)*COS(?) * COS(longitude_radians - ?))) <= ?";
in PHP. Where clause is a function of column values and bind variables
but how should I bind the values. Or is this even a legal prepared stmt?
Thanks in advance,
-v-
I don't see any problem here.
See:
PHP Prepared Statements.
Extremely minimal sample:
$stmt = $dbh->prepare( $QUERY );
$stmt->execute( $arguments_array )
Sorry for being unclear.
As I understand following is an example of PHP prepared stmt,
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
if ($stmt->execute(array($_GET['name'])))
Now the where clause is always a simple, column = ? AND column2 = ?. In my case though its function and it didnt work when assigned values to the bind variables. I will regenerate the error again and post it.
I was wondering then if it is even legal to have a function of column names and bind variables in the where clause.

Categories