4

我知道这个标题听起来很荒谬,但我已经做了几个小时的研究,只是发现 PDO 最终是有缺陷的,没有明显的解决方案……我致力于为一个开放的人。我也愿意接受我的代码有缺陷。

使用 PHP 5.2/Ubuntu,此代码有效(不使用准备好的语句/打开注入):

$sql ="SELECT COUNT(*) FROM property p
INNER JOIN property_attribute pa ON p.property_id = pa.property_id
INNER JOIN property_area pc ON p.property_id = pc.property_id
WHERE pa.attribute_value_id
    IN (
        SELECT av.attribute_value_id
        FROM attribute_value av
        INNER JOIN attribute a ON av.attribute_id = a.attribute_id
        WHERE a.name LIKE '$attributes'
        AND av.value LIKE '$values'
    ) 
ORDER BY p.price ASC";
$params = array();
$rHowManyPages = Listings::HowManyPages($sql, $params);

但是,使用 PDO 的精彩准备语句:

$sql ='SELECT COUNT(*) FROM property p
INNER JOIN property_attribute pa ON p.property_id = pa.property_id
INNER JOIN property_area pc ON p.property_id = pc.property_id
WHERE pa.attribute_value_id
    IN (
        SELECT av.attribute_value_id
        FROM attribute_value av
        INNER JOIN attribute a ON av.attribute_id = a.attribute_id
        WHERE a.name LIKE :attributes
        AND av.value LIKE :values
    ) 
ORDER BY p.price ASC';
$params = array(':attributes' => $attributes, ':values' => $values);
$rHowManyPages = Listings::HowManyPages($sql, $params);

它工作,有点。这是 Spartanic 的疯狂部分:五分之一的刷新相同的数据被传递,PDO 给出了这个错误:

TEXT: SQLSTATE[HY093]: Invalid parameter number

是随机的!如何以及为什么?

4

1 回答 1

5

为命名参数提供的值之一是否可能包含问号?我遇到了一个问题,但那是很久以前的事了。(我当然希望他们现在会解决这个问题。)

以我有限的经验,PDO 对“命名参数”的支持有些粗略。

一方面,您不能在语句的多个位置使用相同的命名参数,每个命名参数的占位符名称必须是唯一的,并且只能使用一次。这让命名论点的一大好处就彻底消失了。

我相信我在值中遇到问号字符的问题,以及无法多次引用命名参数(我尚未确认)是由于 PDO“命名参数”支持是事后的补充支持位置论点;本质上,看起来“命名参数”正在被翻译成位置参数。

当命名参数包含下划线字符时,我也遇到了一些奇怪的问题。

我的解决方法是(ACCCKKK!)使用位置参数而不是命名参数。

(尽管我讨厌使用位置参数,但它对我有用。)

(我在您显示的代码中没有看到任何错误可以解释观察到的行为。显然,您没有显示其他代码。)

此外,您可能想要验证您的$params数组是否仅包含两个元素;当我的数组有一个“额外的”不匹配元素时,我收到了同样的错误消息。再一次,在我的代码中,我退回到只使用标量,并分别绑定每个标量,而不是让 PDO 把它搞砸。(对我来说这不是问题,这是我在 Perl DBI 中过于熟悉的模式。我没有解决问题,而是解决了这些问题。)


注意:通过位置参数,我的意思是使用问号代替名称:

 $sql = " ...
  WHERE a.name LIKE ?
    AND av.value LIKE ?
 ... ";

$sth->bindParam(1, $attributes);
$sth->bindParam(2, $values);
于 2012-07-27T22:19:36.147 回答