P粉6198961452023-09-03 10:06:17
首先,考虑使用命名参数而不是<代码>?代码>。在这种情况下,您不需要替换任何内容:命名参数清晰且相当容易在日志中显示,并且大多数 dbms 客户端都支持用于调试目的。
如果命名参数不可行(由于当前代码库较大或任何其他原因),您有两种主要方法:
如果您选择后一种方式,这里是如何快速而肮脏地完成它的示例:
分多个步骤进行替换:
?
替换为其他极不可能出现在参数或查询中的内容来准备参数。例如\?
。?
,但不会匹配第一步中的替换。如果用 \?
替换,则为 (?
\?
替换为 ?
。注意:此替换的结果不应永远用作程序中的查询。这种替代有可能实现以下任何或所有功能:
?
而不是作为参数(例如在注释中),结果不准确,\?
),结果将不准确。<?php $query = 'UPDATE `list` set `item`=?,`type`=? WHERE (`id` = ?);'; $params = array( 'item' => '1', 'type' => 'Are you o\'k?', 'id' => 2 ); function substitute_params($query, $params) { $prep_params = str_replace(array("'","?"),array("''","\?"),$params); $query = array_reduce($prep_params, function ($interm, $param) { return preg_replace('/(?<!\\)\?/m', is_numeric($param) ? $param : '\'' . $param . '\'', $interm, 1); }, $query); return "-- Not to be used as a query to database. For demonstration purposes only!\n" .str_replace("\?", "?", $query); } echo substitute_params($query, $params); ?>
输出:
-- Not to be used as a query to database. For demonstration purposes only! UPDATE `list` set `item`=1,`type`='Are you o''k?' WHERE (`id` = 2);
编辑:要尝试降低常量字符串和带引号的名称内问号的影响,您可以尝试使用此替换:
return preg_replace('/^([^"\'`]*?(?:(?:`[^`]*?`[^"\'`]*?)*?(?:"[^"]*?"[^"\'`]*?)*?(?:\'[^\']*?\'[^\'"`]*?)*?)*?)(?<!\\)\?/m', ''.(is_numeric($param) ? $param : '\'' . $param . '\''), $interm, 1);
它仅替换用 "`'
引用的块之外的 ?
。
可以在此处查看演示。
请记住,这不是完全成熟的解析器。例如,它不知道评论。因此错误替换的可能性仍然很大。