妙用preg_replace_callback函数

2015-01-15 10:07

怎样妙用preg_replace_callback函数呢?下面就有达内的老是来为学员们介绍一下:

今天在迁移discuz数据的时候我们发现帖子里的content字段经常会有[attach]78[/attach]下面这些题选什么,为什么?  这样用[attach]的标签包括起来的数字,发现这个数字是代表这个帖子内容的附件的id,我们现在不需要找一个[attach]这个标签的内容了。需 要把他替换掉。
首先想到的使用正则把这样的数据替换成其他字符串例如“请查看附件”。想使用preg_replace 来替换,这个也能达到目的。但是后来我们有发现有些content字段里的内容他不只一对[attach]标签,有的有好几对[attach]标签,表示 他有多个附件。接着用上面的preg_replace这个方法替换发现原content里有几对[attach]标签,替换后的结果就有几句“请查看附 件”这样的字符串。这感觉非常不友好。想实现的结果,如果有多对[attach]标签,那么就替换一对为“请查看附件”,其他的都替换为空就行了。
看会下php手册发现了这个函数preg_replace_callback,这个函数的行为除了 可以指定一个callback替代replacement进行替换 字符串的计算, 其他方面等同于preg_replace() 。我们要的就是他的回调函数callback,这里我们可以进行自定义设置。下面举例子吧

0) {   $con =  '';  }else{   $con = " 请查看附件 ";  }  $count++;  return $con; } $result = preg_replace_callback($pat, replace_fn, $content);  var_dump($result); ?> 这样结果就是我们想要的了。 string(38) " 请查看附件 下面这些题选什么,为什么?"。
但是我们现在开发一般是把代码写在类里。例如
class ParseDate {       // 回调函数       function replace_fn($matches) {    global $count;   if ($count > 0) {   $con =  '';  }else{   $con = " 请查看附件 ";  }  $count++;  return $con;     }         function displayText($text) {           echo preg_replace_callback(               "/[attach](d+)[/attach]/",               "$this->replace_fn",               $text);       }   }     $pt = new ParseText();   $pt->displayText($text);
这样写运行后你会发现报错了:preg_replace_callback(): Requires argument 2, '', to be a valid callback in...
为什么会这样?让我们再看一次PHP文档对于preg_replace_callback()函数的定义:
mixed preg_replace_callback ( mixed pattern, callback callback, mixed subject [, int limit] )
仔细看第二个参数callback,并不是字符串类型,而是callback这个伪类型!看看PHP的文档是怎么定义callback这个伪类型的:
callback:
有些诸如 call_user_function() 或 usort() 的函数接受用户自定义的函数作为一个参数。Callback 函数不仅可以是一个简单的函数,它还可以是一个对象的方法,包括静态类的方法。
一个 PHP 函数用函数名字符串来传递。可以传递任何内置的或者用户自定义的函数,除了 array(),echo(),empty(),eval(),exit(),isset(),list(),print() 和 unset()。
一个对象的方法以数组的形式来传递,数组的下标 0 指明对象名,下标 1 指明方法名。
对于没有实例化为对象的静态类,要传递其方法,将数组 0 下标指明的对象名换成该类的名称即可。
如果是要调用对象的方法函数,那么就要用数组的形式来传递。在上面的程序段中,我们错误的想当然的使用了字符串的形式,所以导致PHP无法找到我们想要使用的回调函数。
知道了原因,就好办了,只要简单的把代码改成

preg_replace_callback(”/[attach](d+)[/attach]/”,array( &$this, ‘replace_fn’), $text);

^