php5.5 preg_replace_callback 函數

升級了Mac新系統Yosemite,用着非常舒服,不過每次Mac系統更新,php和apache都要重新折騰一下,這次php的版本從5.4更新到5.5。。。

工作中對一些開源php軟件進行二次開發,升級以後軟件報錯:

preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead

在網上查找原因,函數preg_replace的“/e”修飾符在5.5的版本中已經被棄用,要使用preg_replace_callback() 代替。

“/e” 的作用官方說明如下:當使用被棄用的 e 修飾符時, 這個函數會轉義一些字符(即:'、"、 \ 和 NULL)然後進行後向引用替換。當這些完成後請確保後向引用解析完後沒有單引號或 雙引號引起的語法錯誤(比如: 'strlen(\'$1\')+strlen("$2")')。確保符合PHP的字符串語法,並且符合eval語法。因爲在完成替換後,引擎會將結果字 符串作爲php代碼使用eval方式進行評估並將返回值作爲最終參與替換的字符串。

根據實際使用的情況我理解這個的作用是,使用preg_replace和修飾符以後,字符串被替換爲包含了可執行的php代碼,

舉個栗子:

$html = "<h5>Hello World</h5>";
echo $html;
echo preg_replace(
    '(<h([1-6])>(.*?)</h\1>)e',
    '"<h$1>" . strtoupper("$2") . "</h$1>"',
    $html
);

字符被替換的同時也執行strtoupper函數。其實感覺這種用法怪怪的。。。

其實要我寫我會寫成   

if(preg_match('(<h([1-6])>(.*?)</h\1>)', $html, $m)){

    echo "<h{$m[1]}>" . strtoupper($m[2]) . "</h{$m[1]}>";

}

這樣更容易讀懂。。。

下面說說 preg_replace_callback,它替代了preg_replace的“/e”修飾符,不過用起來也很怪。。。

echo preg_replace_callback(
    '(<h([1-6])>(.*?)</h\1>)',
    function ($m) {
        return "<h$m[1]>" . strtoupper($m[2]) . "</h$m[1]>";
    },
    $html
);

執行一個正則表達式搜索並且使用一個回調進行替換,其實和preg_match匹配有點像。

解釋完preg_replace_callback這個函數看看實際中解決問題。

以下代碼現在開源軟件的模板引擎好像很多都用到了,

preg_replace("/{([^\}\{\n]*)}/e", "\$this->select('\\1');", $source);

改成

preg_replace_callback(
                "/{([^\}\{\n]*)}/",
                function ($m) {
                    return $this->select($m[1]);
            },
            $source
        );

下面這段數組替換沒想到更好的方法

$pattern = array(
    '/<!--[^>|\n]*?({.+?})[^<|{|\n]*?-->/', // 替換smarty註釋
    '/<!--[^<|>|{|\n]*?-->/',               // 替換不換行的html註釋
    '/(href=["|\'])\.\.\/(.*?)(["|\'])/i',  // 替換相對鏈接
    '/((?:background|src)\s*=\s*["|\'])(?:\.\/|\.\.\/)?(images\/.*?["|\'])/is', // 在images前加上 $tmp_dir
    '/((?:background|background-image):\s*?url\()(?:\.\/|\.\.\/)?(images\/)/is', // 在images前加上 $tmp_dir
    '/{nocache}(.+?){\/nocache}/ise', //無緩存模塊
    );
$replace = array(
    '\1',
    '',
    '\1\2\3',
    '\1' . $tmp_dir . '\2',
    '\1' . $tmp_dir . '\2',           
    "'{insert name=\"nocache\" ' . '" . $this->_echash . "' . base64_encode('\\1') . '}'",
    );
preg_replace($pattern, $replace, $source);


只想到分步進行替換

      $pattern = array(
            '/<!--[^>|\n]*?({.+?})[^<|{|\n]*?-->/', // 替換smarty註釋
            '/<!--[^<|>|{|\n]*?-->/',               // 替換不換行的html註釋
            '/(href=["|\'])\.\.\/(.*?)(["|\'])/i',  // 替換相對鏈接
            '/((?:background|src)\s*=\s*["|\'])(?:\.\/|\.\.\/)?(images\/.*?["|\'])/is', // 在images前加上 $tmp_dir
            '/((?:background|background-image):\s*?url\()(?:\.\/|\.\.\/)?(images\/)/is', // 在images前加上 $tmp_dir
//             '/{nocache}(.+?){\/nocache}/ise', //無緩存模塊
            );
        $replace = array(
            '\1',
            '',
            '\1\2\3',
            '\1' . $tmp_dir . '\2',
            '\1' . $tmp_dir . '\2',
//             "'{insert name=\"nocache\" ' . '" . $this->_echash . "' . base64_encode('\\1') . '}'",
            );
          
//      preg_replace($pattern, $replace, $source);
  
        ###php5.5 preg_replace 不能使用 \e 參數
        $source = preg_replace($pattern, $replace, $source);
          
        preg_replace_callback(
                '/{nocache}(.+?){\/nocache}/is',
                function ($m) {
                    return '{insert name=\"nocache\" ' .$this->_echash . base64_encode($m[1]) . '}';
                },
                $source
        );
    }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章