2011-03-13 136 views
1

我注意到一個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?

回答

7

的文檔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替換爲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

0

因爲一旦你用3代替2的下一個替換將始終以4

3

如果使用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"