我想通过将表达式乘以:firstname
数组中的元素来替换查询的参数$firstnames
。
这是我到目前为止所得到的:
$query = "SELECT * FROM test WHERE col1 IN(UNHEX(:firstname)) OR IN (UNHEX('foo'))";
$firstnames = array("Jack", "John", "Michael");
$replacement = "";
foreach ($firstnames as $key => $value) {
$replacement .= "\${1}".$key.",";
}
$replacement = rtrim($replacement,",");
$pattern = "/(:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)/i";
$query = (preg_replace($pattern, $replacement, $query)).",";
echo $query;
到目前为止,我只更换了参数,但没有替换它周围的函数。可能还有其他几个函数或字符串连接也应该是重复替换的一部分。也可能有一些嵌套的括号。因此,这将是获取IN语句的所有嵌套括号的模式:
$pattern= "/(\s*IN\s*)(\(((?>[^()]+)|(?2))*\))/i";
我无法找到一种方法来组合这两个语句,以正确地替换参数和包裹它的东西。另外,如果IN语句中没有参数,则不应替换。这应该是结果:
$query = "SELECT * FROM test WHERE col1 IN(UNHEX(:firstname1), UNHEX(:firstname2), UNHEX(:firstname3)) OR IN (UNHEX('foo'))";
更新:解决方案! 与此同时,我偶然发现了几个问题,但最终解决了这个问题。
似乎不可能通过使用正则表达式来获取所有内容。因此我决定使用preg_replace_callback
功能。在第一步中,我得到了整个IN函数,由它的所有嵌套括号决定。在第二步中,我得到参数,用所需的重复次数替换它。
以下解决方案:
$params = array(
"firstname" => array("Jack", "John", "Michael")
);
$query = "SELECT * FROM test WHERE col1 IN (UNHEX(:firstname)) OR col2 IN(UNHEX('foo'))";
function createIN($query, $arrParam) {
return preg_replace_callback(
"/(\\s*IN\s*(\\((?:(?>[^()]+)|(?2))*\)))/is",
function ($matches) use($arrParam) {
$pattern = "/(\s*IN\s*\()((.*?((['\"`]).*?\5)?)*)(:[a-zA-Z_][a-zA-Z0-9_]*)(.*)(\))/is";
preg_match($pattern, $matches[1], $matches2);
$replacement = $matches[0];
if(isset($matches2[6])) {
$replacement = $matches2[1];
foreach ($arrParam[substr($matches2[6],1)] as $key => $value) {
$replacement .= $matches2[2].$matches2[6].$key.$matches2[7].",";
}
$replacement = rtrim($replacement,",").$matches2[8];
}
return $replacement;
},
$query
);
}
echo createIN ($query, $params);
答案 0 :(得分:1)
动态创建查询,并使用预准备语句。一种简单的方法是将每个参数名称添加到数组中,然后使用implode()将数组转换为逗号分隔的名称列表。这个例子应该有效:
$query = "SELECT * FROM test WHERE col1 IN(";
$firstnames = array("Jack", "John", "Michael");
$params = array();
$query_in = array();
foreach ($firstnames as $key => $value) {
//$params[] = $value;
//$query_in[] = "?";
// Use this for named parameters:
$params[":param".$key] = $value;
$query_in[] = ":param".$key;
}
$query .= implode(",",$query_in);
$query .= ") OR IN (UNHEX('foo'))";
/** @var PDO $pdo */
$stm = $pdo->prepare($query);
$stm->execute($params);
echo $stm->queryString;
答案 1 :(得分:1)
如果您真的在寻找正则表达式解决方案:
更改评论:
最后:
$query = "SELECT * FROM test WHERE col1 IN(UNHEX(CONCAT(UPPER(CONCAT(:firstname, 'baz')), 'bar', 'quz'))) OR col1 IN (UNHEX('foo'))";
$firstnames = array("Jack", "John", "Michael");
$pattern = '/((\w+\()+:firstname)(\D+)*((\))+)/i';
if (preg_match($pattern, $query, $matches) === 1) {
$match = substr(preg_replace('/(IN\s*\()/i', '', $matches[0]), 0 ,-1);
$function = substr($match, 0, strpos($match, ':firstname'));
$brackets = substr($match, strpos($match, ':firstname')+10);
foreach ($firstnames as $key => $value) {
isset($replacement) ? $replacement .= ",{$function}:firstname{$key}{$brackets}" : $replacement = "{$function}:firstname{$key}{$brackets}";
}
}
$query = str_replace($match, $replacement, $query);
echo $query;
$query = SELECT * FROM test WHERE col1 IN(UNHEX(CONCAT(UPPER(CONCAT(:firstname0, 'baz')), 'bar', 'quz')),UNHEX(CONCAT(UPPER(CONCAT(:firstname1, 'baz')), 'bar', 'quz')),UNHEX(CONCAT(UPPER(CONCAT(:firstname2, 'baz')), 'bar', 'quz'))) OR col1 IN (UNHEX('foo'))
希望有所帮助。
真的终于:
$query = "SELECT * FROM test WHERE col1 IN(UNHEX(CONCAT('paz', UPPER(CONCAT('qaz', 'qar', :firstname, 'baz')), 'bar', 'quz'))) OR col1 IN(UNHEX(CONCAT('paz', UPPER(CONCAT('qaz', 'qar', :lastname, 'baz')), 'bar', 'quz'))) OR col1 IN (UNHEX('foo'))";
$firstnames = array("Jack", "John", "Michael");
$parameters = array(':firstname', ':street', ':lastname');
$pattern = '/((\w+\()+)(\D+)(:[a-z])(\D+)*((\))+)/i';
if (preg_match_all($pattern, $query, $matches) >= 1) {
$tempMatches = array();
if (is_array($matches[0])) {
foreach ($matches[0] as $moreMatches) {
$tempMatches[] = $moreMatches;
}
} else {
$tempMatches[] = $matches[0];
}
foreach ($tempMatches as $myMatches) {
$match = substr(preg_replace('/(IN\s*\()/i', '', $myMatches), 0 , -1);
foreach ($parameters as $param) {
if (strpos($myMatches, $param)) {
$function = substr($match, 0, strpos($match, $param));
$brackets = substr($match, strpos($match, $param) + strlen($param));
foreach ($firstnames as $key => $value) {
isset($replacement) ? $replacement .= ",{$function}{$param}{$key}{$brackets}" : $replacement = "{$function}{$param}{$key}{$brackets}";
}
$query = str_replace($match, $replacement, $query);
unset($replacement);
}
}
}
}
echo $query;
output = SELECT * FROM test WHERE col1 IN(UNHEX(CONCAT('paz', UPPER(CONCAT('qaz', 'qar', :firstname0, 'baz')), 'bar', 'quz')),UNHEX(CONCAT('paz', UPPER(CONCAT('qaz', 'qar', :firstname1, 'baz')), 'bar', 'quz')),UNHEX(CONCAT('paz', UPPER(CONCAT('qaz', 'qar', :firstname2, 'baz')), 'bar', 'quz'))) OR col1 IN(UNHEX(CONCAT('paz', UPPER(CONCAT('qaz', 'qar', :lastname0, 'baz')), 'bar', 'quz')),UNHEX(CONCAT('paz', UPPER(CONCAT('qaz', 'qar', :lastname1, 'baz')), 'bar', 'quz')),UNHEX(CONCAT('paz', UPPER(CONCAT('qaz', 'qar', :lastname2, 'baz')), 'bar', 'quz'))) OR col1 IN (UNHEX('foo'))