为什么带有命名参数的查询返回空白结果?

时间:2012-10-02 11:04:04

标签: php pdo sql-injection

我正在将我的MySQL代码转换为PDO以利用预准备语句。我最初得到致命错误,如this question所述。我已经解决了这个问题,但在尝试添加参数时会带来更多问题。

我正在尝试的代码是:

include ("foo/bar.php");

try {
     $DBH = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
    }  
catch(PDOException $e) {  
    echo $e->getMessage();  
    }

    $mydate=date("Y-m-d",strtotime("-3 months"));

    $foo_query=$DBH->prepare("SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body FROM BarTable WHERE postdate = :postdate AND postdate > '$mydate' ORDER BY postdate DESC");
    $foo_query->execute( array('postdate' => $_REQUEST['postdate']) );

    $DBH=null;

在英语中,这意味着“取当前日期并将其设置为3个月,称之为$ mydate,然后选择所有这些字段(同时取出正文的前20个字并称之为'我的表中的preview_text'),其中postdate等于参数postdate,其中postdate大于$ mydate “。

然后我在下面显示结果(请注意,现在已删除):

$foo_query->setFetchMode(PDO::FETCH_ASSOC);
    while($r=$foo_query->fetch()) {
    echo $r["id"];
    echo $r["title"];
    echo date("d-M-Y",strtotime($r["postdate"]));
    echo nl2br ($r["preview_text"]); }

现在,SELECT查询写成:

("SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body FROM BarTable WHERE postdate > '$mydate' ORDER BY postdate DESC")

...它显示我需要它的确切内容,但当然在准备时,它不包含任何参数,因此只能达到目标的50%。

我的印象是,根据我已经给出的教程和建议,我最初概述的陈述的准备方式会很好。

我试图打印我的错误,但没有出现任何错误。我按如下方式手动发送查询并且没有返回。注意我已经以各种排列方式尝试了日期字符串:

("SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body FROM BarTable WHERE postdate = 20121001 AND postdate > 20120701 ORDER BY postdate DESC")

编辑:上述内容被指出不正确,但我会将其保留在此作为参考,因为此部分将在下面的评论中进行解释。

编辑:输入时,现在可以正确显示手动发送查询:

("SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body FROM BarTable WHERE postdate = '2012-09-30 08:38:23' ORDER BY postdate DESC")

键入以下任何内容时,查询根本不显示:

("SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body FROM BarTable WHERE postdate = :postdate ORDER BY postdate DESC")
("SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body FROM BarTable WHERE postdate = :postdate AND postdate > '$mydate' ORDER BY postdate DESC")
("SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body FROM BarTable WHERE postdate = '2012-09-30 08:38:23' AND postdate > '2012-07-01 00:01' ORDER BY postdate DESC")

我在想我应该以某种方式绑定参数,但我读过的教程没有具体说我应该总是绑定它们 - 我不确定如何继续。

编辑:我希望将语句绑定如下,但没有成功。查询似乎忽略了绑定,因此查询的状态充当上述所有排列而没有绑定:

$foo_query->bindParam (
   ":postdate", strtotime ( $_REQUEST['postdate']), PDO::PARAM_INT);
$foo_query->execute();

我做错了什么,当我不添加参数时没有发生这种情况?我应该在SELECT查询以外的地方声明:postdate参数吗?

为了防止SQL注入,我想使用命名参数以及准备语句,但如果我无法弄清楚,那么我将不得不使用命名参数。

1 个答案:

答案 0 :(得分:1)

通过数组使用参数时,您将使用默认参数类型PDO::PARAM_STR

进行绑定

取决于数据类型:

  • MySQL时间戳数据类型:它是相同的,你将它作为一个字符串传递
  • PHP Unix时间戳,它是一个整数:你将它传递给一个int。

我建议你改变你的代码:

$foo_query=$DBH->prepare(
   "SELECT id, postdate, title, SUBSTRING_INDEX(body,' ',20) as preview_text, body 
    FROM BarTable WHERE postdate = :postdate 
    ORDER BY postdate DESC");
$foo_query->bindParam (
   ":postdate", strtotime ( $_REQUEST['postdate']), PDO::PARAM_INT); 
//                                                  ^^^ bind as integer
$foo_query->execute();