在我们的Web应用程序中,我们有一个类,它模拟准备好的语句以正确转义SQL参数。
现在,我现在使用PDO
会好得多,但是应用程序已经很老了,重构可能会很长,所以目前我只是想修复一个我发现的错误。
考虑使用我们的类的这段代码:
$s = Q()->statement("SELECT * FROM DUAL WHERE 1 = :a AND 2 = :b AND 3 = :c");
$s->bindValue('c', ':b');
$s->bindValue('b', ':a');
$s->bindValue('a', ':c');
var_dump($s->prepared);
第一行创建语句,然后绑定一些值,然后我转储预准备语句。
结果如下:
SELECT * FROM DUAL WHERE 1 = ':c' AND 2 = '':c'' AND 3 = ''':c'''
这是因为参数从最后一个到第一个被一次替换。
我还尝试在单个函数调用中使用带有数组参数的str_replace()
进行替换,但无济于事。
所以我想知道是否有办法使这个操作以某种方式“原子化”,这样如果占位符值是另一个有效的占位符,它就不会被替换。
编辑:
以下是我班级的替代方法:
protected function prepare() {
if (!$this->db) {
trigger_error (__METHOD__ . ': no Connection available to properly quote the value', E_USER_WARNING);
return false;
}
$this->prepared = str_replace(
array_map(array($this, 'getPlaceholderName'), array_keys($this->params)),
array_map(array($this->db, 'quote'), array_values($this->params)),
$this->original
);
return true;
}
答案 0 :(得分:2)
您可能希望只使用数组签名对旧的strtr()进行一次调用:
string strtr(string $ str,array $ replace_pairs)
当然,普通字符串替换只是一种破解,永远无法替换正确的SQL解析器,但我想你已经知道了。
答案 1 :(得分:0)
这是您要使用的代码:
$queryString = strtr($queryString, array(":a" => "b",":b"=>"c", ":c" => "a"));