Php 如何用数组中的元素替换所有出现的字符?
我有以下字符串:Php 如何用数组中的元素替换所有出现的字符?,php,mysql,replace,Php,Mysql,Replace,我有以下字符串: $sql = sql_prepare("UPDATE `test` SET `item1` = ?, `item2` = ?, `item3` = ?", array(50, 55, 60)); 我需要创建“sql_prepare”函数,该函数将匹配所有出现的“?”字符,并替换为数组中的元素,因此最终sql将为: UPDATE `test` SET `item1` = 50, `item2` = 55, `item3` = 60 我该怎么做呢?既然mysqli和PDO都实现
$sql = sql_prepare("UPDATE `test` SET `item1` = ?, `item2` = ?, `item3` = ?", array(50, 55, 60));
我需要创建“sql_prepare”函数,该函数将匹配所有出现的“?”字符,并替换为数组中的元素,因此最终sql将为:
UPDATE `test` SET `item1` = 50, `item2` = 55, `item3` = 60
我该怎么做呢?既然mysqli和PDO都实现了真正的预处理语句,为什么还要用传统的mysql_*API来伪造预处理语句呢 PDO示例:
if ($prepped = $pdo -> prepare ('UPDATE `test` SET `item1` = ?, `item2` = ?, `item3` = ?'))
{
$res = $prepped -> execute (array (50, 55 ,60));
}
对于这种简单的替换,您可以使用sprintf格式:
$sql = vsprintf("UPDATE `test` SET `item1` = %d, `item2` = %d, `item3` = %d",
array(50, 55, 60));
但是,对于实际使用,最好制作不同类型的占位符
下面是我的db类中的代码
private function prepareQuery($args)
{
$raw = $query = array_shift($args);
preg_match_all('~(\?[a-z?])~',$query,$m,PREG_OFFSET_CAPTURE);
$pholders = $m[1];
$count = 0;
foreach ($pholders as $i => $p)
{
if ($p[0] != '??')
{
$count++;
}
}
if ( $count != count($args) )
{
throw new E_DB_MySQL_parser("Number of args (".count($args).") doesn't match number of placeholders ($count) in [$raw]");
}
$shift = 0;
$qmarks = 0;
foreach ($pholders as $i => $p)
{
$pholder = $p[0];
$offset = $p[1] + $shift;
if ($pholder != '??')
{
$value = $args[$i-$qmarks];
}
switch ($pholder)
{
case '?n':
$value = $this->escapeIdent($value);
break;
case '?s':
$value = $this->escapeString($value);
break;
case '?i':
$value = $this->escapeInt($value);
break;
case '?a':
$value = $this->createIN($value);
break;
case '?u':
$value = $this->createSET($value);
break;
case '??':
$value = '?';
$qmarks++;
break;
default:
throw new E_DB_MySQL_parser("Unknown placeholder type ($pholder) in [$raw]");
}
$query = substr_replace($query,$value,$offset,2);
$shift+= strlen($value) - strlen($pholder);
}
$this->lastquery = $query;
return $query;
}
我必须承认转义
?
标记解决方案并不优雅,但这正是我迄今为止所得到的。为什么不使用真正预先准备好的语句呢@KingCrunch,因为它们速度慢、使用不便,而且不足以防止注射?@donkeyKong:既然有大量内置数据库类(mysqli、PDO)和第三方数据库类(mdb2、zend_db等),为什么要重新发明轮子呢?@Col:Sharapinel:你能用一些事实来支持这一说法吗?(因为如果PHP的预处理语句中存在缺陷,以及它们针对SQL注入提供的保护量,我真的很想知道)也许我找到了一个解决方案:函数SQL\u prepare($SQL,$params){$SQL=preg\u replace('/\?/e','escape(array\u shift($params)),$SQL;return$SQL;}我有一个代码,可以检测变量类型并在需要时转义它们。哈哈,你没有明白:)这与变量类型无关。它是关于占位符类型的。您的变量类型检测可能会失败。老实说,我不认为放置不同的占位符有什么意义。变量类型检测如何失败?您可以在这段代码中看到它。它可以从数组中为您生成SET语句。对IN语句也是如此。它可以为您转义一个标识符。这就是键入占位符的要点。类型检测可能因类型错误而失败。比如说,GET变量总是字符串。我更喜欢手动执行SET和IN语句。关于数据类型-关于GET变量,您是正确的。但当我需要正确处理的时候,我只会做打字。转义将如预期的那样工作。mooom,为什么PHP允许伪造准备好的语句,而我不允许?;-)1) 没有必要粗鲁,2)请不要表现得好像PDO准备的声明中存在的任何问题都是不言而喻的,并准确解释它们的错误。如果PDO和/或mysqli中确实存在问题,那么更广泛的社区需要知道,我自己也很想知道,以避免在我自己的项目中出现任何问题。请您解释一下,我的评论有什么粗鲁之处?我不是以英语为母语的人,在某些表达上可能会被忽略。我很乐意纠正它。先谢谢你。嗯,Mooom,乍一看,看起来像Moooan(拖长的呻吟),这使得你的评论看起来像是在贬低或讽刺。很抱歉没有注意到它不是Moooan,但看起来确实是这样。(顺便说一句,mooom到底是什么意思?)我当时正试图嘲笑一个孩子对妈妈的孩子气抱怨,因为孩子不允许做别人做的事情。这只是个玩笑,无意冒犯任何人。PDO(不是PHP-我的错误)默认情况下也会伪造准备好的语句。它在内部进行替换,并将通常的查询发送到mysql服务器。您必须显式地启用本机准备语句支持。