erawrq 发表于 2015-3-30 09:35:01

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代码,

举个栗子:
1
2
3
4
5
6
7
$html = "<h5>Hello World</h5>";
echo $html;
echo preg_replace(
    '(<h()>(.*?)</h\1>)e',
    '"<h$1>" . strtoupper("$2") . "</h$1>"',
    $html
);




字符被替换的同时也执行strtoupper函数。其实感觉这种用法怪怪的。。。

其实要我写我会写成   if(preg_match('(<h()>(.*?)</h\1>)', $html, $m)){
    echo "<h{$m}>" . strtoupper($m) . "</h{$m}>";
}
这样更容易读懂。。。

下面说说 preg_replace_callback,它替代了preg_replace的“/e”修饰符,不过用起来也很怪。。。

1
2
3
4
5
6
7
echo preg_replace_callback(
    '(<h()>(.*?)</h\1>)',
    function ($m) {
      return "<h$m>" . strtoupper($m) . "</h$m>";
    },
    $html
);




执行一个正则表达式搜索并且使用一个回调进行替换,其实和preg_match匹配有点像。

解释完preg_replace_callback这个函数看看实际中解决问题。

以下代码现在开源软件的模板引擎好像很多都用到了,
preg_replace("/{([^\}\{\n]*)}/e", "\$this->select('\\1');", $source);
改成
1
2
3
4
5
6
7
preg_replace_callback(
                "/{([^\}\{\n]*)}/",
                function ($m) {
                  return $this->select($m);
            },
            $source
      );




下面这段数组替换没想到更好的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$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);





只想到分步进行替换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
      $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) . '}';
                },
                $source
      );
    }



页: [1]
查看完整版本: php5.5 preg_replace_callback 函数