简体   繁体   中英

PHP PDO custom sql query preparation

I'm having a little problem getting a sql query with prepare on PDO, I have this code:

$portfolio = $db->prepare("SELECT * FROM `news`, `:sub` WHERE `news`.`id` = `:sub`.`id_news` AND `page` = `:under` ORDER BY `date` DESC LIMIT :start, :limit");
$portfolio->bindParam(':under', $_GET['under'], PDO::PARAM_STR);
$portfolio->bindParam(':sub', $_GET['sub'], PDO::PARAM_STR);
$portfolio->bindParam(':start', $start, PDO::PARAM_INT);
$portfolio->bindParam(':limit', $limit, PDO::PARAM_INT);
$portfolio->execute();

But this doesn't give any value and my DB has the values correct, any one knows why this doesn't work? PS: var $start and $limit are fine, no problem with it cuz it's pagination script, that work very fine in all the pages.

For exemple i'm in the url: mysite.com/index.php?sub=vid&under=info

so the query should be like this:

"SELECT * FROM `news`, `vid` WHERE `news`.`id` = `vid`.`id_news` AND `page` = `info` ORDER BY `date` DESC LIMIT 0, 10"

So for what i understood having this code before should work and still be safe right?

switch($_GET['sub']){
    case "vid":
        $table = "vid";
        break;
    case "img":
        $table = "img";
        break;
}
$portfolio = $db->prepare("SELECT * FROM `news`, `$table` WHERE `news`.`id` = `$table`.`id_news` AND `page` = :under ORDER BY `date` DESC LIMIT :start, :limit");

You can't use query parameter placeholders for table names or column names.

Use query parameters only to substitute for a literal value in an expression. Ie a quoted string, quoted date, or numeric value.

Also, even if you are using a parameter for a string or date, the parameter doesn't go inside quotes.

To make table names or column names dynamic, you have to interpolate application variables into your SQL string before you submit the string to prepare().

But be careful to validate user input (eg $_GET variables) so you avoid SQL injection. For instance, test the input against a list of known legitimate table names.

Example:

$subtables = array(
 "DEFAULT" => "text",
 "text" => "text",
 "vid" => "vid",
 "pic" => "pic"
);

// if the key exists, use the table name, else use the default table name
$subtable = $subtables[ $_GET["sub"] ] ?: $subtables[ "DEFAULT" ];

// now $subtable is effectively whitelisted, and it is safe to use
// without risk of SQL injection

$portfolio = $db->prepare("SELECT * 
  FROM news, `$subtable` AS sub 
  WHERE news.id = sub.id_news 
    AND page = :under 
  ORDER BY date DESC LIMIT :start, :limit");

You can't use parameters for the names of tables and table object (ie fields). See this question where this is covered.

Can PHP PDO Statements accept the table or column name as parameter?

$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );

are two magical lines that will solve all your minor problems after you fix the BIGGEST one - a dynamically linked table.

What it have to be is a single table where "sub" is a field name to distinguish a category

SELECT * FROM news n, subnews s 
WHERE n.id = id_news AND s.sub =:sub AND `page` = :under 
ORDER BY `date` DESC LIMIT :start, :limit

Also you have to quit that habit of wrapping in backticks everything that moves.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM