我知道这个标题听起来很荒谬,但我已经做了几个小时的研究,现在却发现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疯狂部分:传递相同数据的刷新中有1个,PDO给出了这个错误:
TEXT: SQLSTATE[HY093]: Invalid parameter number
这是随机的!怎么样和为什么?
答案 0 :(得分: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);