preg_replace - не заменять в уже замененных деталях - PullRequest
0 голосов
/ 18 января 2020

Учитывая SQL -запрос с местозаполнителями:

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

и параметрами запроса ['aaa', 'bbb'], я хотел бы заменить? -Заполнители соответствующими параметрами. Итак, я делаю это так:

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

(мы не концентрируемся на mysql -экранировании, цитировании и т. Д. c. В этом вопросе).

Все работает нормально и Я получаю

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

Но если наш первый параметр выглядит так: «? Aa», все терпит неудачу:

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

очевидно, первый проход замены заменяет «a =?» в "a =? aa", а второй проход меняет этот (только что вставленный) вопросительный знак на "bbb".

Вопрос: как мне обойти это запутанное поведение preg_replace?

Ответы [ 2 ]

2 голосов
/ 18 января 2020

Вы можете использовать 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);

Дайте мне знать

0 голосов
/ 18 января 2020

Я бы не стал делать это с preg_replace или str_replace. Я бы использовал preg_split, чтобы можно было удалить пустые возвраты (если бы у explode была пустая опция удаления, я бы использовал это). Ибо там перебрать возврат и добавить в значения. Вы также можете указать значения с этим. Я предполагаю, что целью этого является отладка параметризованных запросов.

$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'
...