preg_replace - 不要更换已经更换的部件

preg_replace - don't replace in already replaced parts

给定 SQL- 带占位符的查询:

SELECT * FROM table WHERE `a`=? AND `b`=?

和查询参数 ['aaa'、'bbb'],我想用相应的参数替换 ?-placeholders。所以,我这样做:

$sql = preg_replace(array_fill(0, count($params), '#\?#'), $params, $sql, 1);

(本题不关注mysql-转义、引用等)

一切正常,我得到了

SELECT * FROM table WHERE `a`=aaa AND `b`=bbb

但是如果我们的第一个参数是这样的:“?aa”,一切都失败了:

SELECT * FROM table WHERE `a`=bbba AND `b`=?

显然,第一个替换过程将 "a=?" 更改为 "a=?aa",第二个替换过程将这个(刚刚插入的)问号更改为 "bbb".

问题是:如何绕过这种令人困惑的 preg_replace 行为?

我不会用 preg_replacestr_replace 这样做。我会使用 preg_split,这样可以删除空的 returns(如果 explode 有空的删除选项,我会使用它)。因为那里遍历 return 并添加值。您也可以用这个引用值。我认为这样做的目的是为了调试参数化查询。

$sql = 'SELECT * FROM table WHERE `a`=? AND `b`=?';
$v = array('1?1', "222");
$e = preg_split('/\?/', $sql, NULL, PREG_SPLIT_NO_EMPTY);
$c = '';
foreach($e as $k => $v1){
    $c .= $v1 . "'" . $v[$k] ."'"; 
}
error_log($c);

那么你的错误日志将有:

SELECT * FROM table WHERE `a`='1?1' AND `b`='222'

您可以使用 preg_replace_callback 每次替换使用 $params 中的一项。

$sql = 'SELECT * FROM table WHERE `a`=? AND `b`=?';
var_dump('Original: ' . $sql);
$params=['aaa','bbb'];

$sql = preg_replace_callback("/\?/",function($m) use (&$params) {
    return array_shift($params);
}, $sql);

var_dump('Result: ' . $sql);

告诉我