1

我在 PDO 上使用 prepare 获取 sql 查询时遇到了一点问题,我有以下代码:

$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();

但这并没有给出任何价值,而且我的数据库的值是正确的,有人知道为什么这不起作用吗?PS: var $start 和 $limit 没问题,因为它是分页脚本,在所有页面中都可以正常工作。

例如,我在网址中:mysite.com/index.php?sub=vid&under=info

所以查询应该是这样的:

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

因此,据我所知,之前拥有此代码应该可以工作并且仍然是安全的,对吗?

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");
4

3 回答 3

2

您不能将查询参数占位符用于表名或列名。

仅使用查询参数替换表达式中的文字值。即带引号的字符串、带引号的日期或数值。

此外,即使您将参数用于字符串或日期,该参数也不会放在引号内。

要使表名或列名动态化,您必须在将字符串提交给 prepare()之前将应用程序变量插入到 SQL 字符串中。

要小心验证用户输入(例如 $_GET 变量),以避免 SQL 注入。例如,根据已知合法表名列表测试输入。

例子:

$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");
于 2013-09-30T15:59:05.230 回答
-1

您不能将参数用于表和表对象(即字段)的名称。请参阅此问题。

PHP PDO 语句可以接受表名或列名作为参数吗?

于 2013-09-30T16:01:47.613 回答
-2
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );

是两条神奇的线,将在您修复最大的线后解决您的所有小问题 - 动态链接表。

它必须是一个单独的表,其中“sub”是用于区分类别的字段名称

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

此外,您必须戒掉将所有移动的东西都用反引号括起来的习惯。

于 2013-09-30T16:00:53.157 回答