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服务器。您必须显式地启用本机准备语句支持。