PHP:问题与str_replace函数

问题描述:

我注意到一个str_replace函数功能的一个奇怪的行为。 你能告诉我为什么,而不是在NO_2 3号我得到no_4PHP:问题与str_replace函数

这里的情况:

$pattern = array(1,2,3); 
$change = array(1,3,4); 
$sql = "SELECT * FROM %s WHERE no_1 IN (%s) AND no_2 IN (%s) AND no_3 IN (%s)"; 

$test_multiply[] = str_replace($pattern, $change, $sql); 

其中给出:

Array ([0] => SELECT * FROM %s WHERE no_1 IN (%s) AND no_4 IN (%s) AND no_4 IN (%s)) 

你能告诉我该怎么办收到NO_3而不是NO_2?

的文档str_replace()说:(引用)

因为str_replace()函数替换左到右 ,它可能会进行多次 替换时替换以前 插入值。

我相信你也正是在这种情况下:

  • no_2被替换到no_3 - 在你$pattern$change阵列
  • 但是,由于第二项目的话,那由于您的$pattern$change ar的射线


为了避免这种情况的具体情况,你可以尝试扭转这两个数组项目的顺序:

$pattern = array(3, 2, 1); 
$change = array(4, 3, 1); 

而且你会得到以下结果:

SELECT * FROM %s WHERE no_1 IN (%s) AND no_3 IN (%s) AND no_4 IN (%s) 
+0

好的。那么这种情况的解决方案是什么? – elfuego1 2011-03-13 10:43:06

+0

@elfuego我已经编辑了我的答案,并提供了一个可能的解决方案 – 2011-03-13 10:43:48

+0

这个完美正是我所需要的。非常感谢Martin! – elfuego1 2011-03-13 12:39:44

首先,您将1替换为1,这样就可以了。

SELECT * FROM %s WHERE no_1 IN (%s) AND no_2 IN (%s) AND no_3 IN (%s)

然后,更换2连3,获得

SELECT * FROM %s WHERE no_1 IN (%s) AND no_3 IN (%s) AND no_3 IN (%s)

然后用4代替3,导致 SELECT * FROM %s WHERE no_1 IN (%s) AND no_4 IN (%s) AND no_4 IN (%s)

也许你应该与另一个值(不是3)更换2,您可以稍后再进行更换。

+0

有没有办法解决它? – elfuego1 2011-03-13 10:43:48

因为一旦你用3代替2的下一个替换将始终以4

如果使用str_replace与针阵列代替3,每针被替换在一个单独的呼叫str_replace。你能想象这样的事情在内部发生:

for ($i=0, $n=min(count($pattern),count($change)); $i<$n; $i++) { 
    $sql = str_replace($pattern[$i], $change[$i], $sql); 
} 

所以在第一次迭代所有11代替,那么所有23置换后,所有34取代:

  1. SELECT * FROM %s WHERE no_1 IN (%s) AND no_2 IN (%s) AND no_3 IN (%s)
  2. SELECT * FROM %s WHERE no_1 IN (%s) AND no_3 IN (%s) AND no_3 IN (%s)
  3. SELECT * FROM %s WHERE no_1 IN (%s) AND no_4 IN (%s) AND no_4 IN (%s)

要做到同时更换,你可以使用preg_replace_callback并调用映射函数对每个匹配的模式:

function str_replacep(array $search, array $replace, $subject, &$count=0) { 
    $combinedPattern = '/(?:'.implode('|', array_map(function($str) { return preg_quote($str, '/'); }, $search)).')/'; 
    $map = array_combine($search, $replace); 
    $mapping = function($match) use ($map, $count) { 
     $count++; 
     return $map[$match[0]]; 
    }; 
    return preg_replace_callback($combinedPattern, $mapping, $subject); 
} 

我在这个例子中使用anonymous function,但它也将与create_function工作。

有了这个替换的顺序并不重要。你甚至可以交换两个值:

var_dump(str_replacep(array(1,2), array(2,1), "12")); // string(2) "21"