preg_replace_callback()调用类中的回调函数

最近项目中使用preg_replace_callback,需要使用它执行正则匹配时回调类中的方法,需要有一些注意的地方,做个记录。

PHP文档中这样介绍 preg_replace_callback:(PHP 4 >= 4.0.5, PHP 5中可以使用),该方法用回调函数执行正则表达式的搜索和替换,本函数的行为几乎和 preg_replace() 一样,除了不是提供一个 replacement 参数,而是指定一个 callback 函数。该函数将以目标字符串中的匹配数组作为输入参数,并返回用于替换的字符串。

所以,我们可以这样使用这个函数,下面是PHP手册中的例子:

// 此文本是用于 2002 年的,
// 现在想使其能用于 2003 年
$text = "April fools day is 04/01/2002/n"; 
$text.= "Last christmas was 12/24/2001/n"; 
// 回调函数
function next_year($matches) { 
// 通常:$matches[0] 是完整的匹配项
// $matches[1] 是第一个括号中的子模式的匹配项
// 以此类推
return $matches[1].($matches[2]+1); 
} 
echo preg_replace_callback( 
"|(/d{2}//d{2}/)(/d{4})|", 
"next_year", 
$text); 
// 结果为:
// April fools day is 04/01/2003
// Last christmas was 12/24/2002
  // 此文本是用于 2002 年的,
  // 现在想使其能用于 2003 年
  $text = "April fools day is 04/01/2002/n";
  $text.= "Last christmas was 12/24/2001/n";
  // 回调函数
  function next_year($matches) {
    // 通常:$matches[0] 是完整的匹配项
    // $matches[1] 是第一个括号中的子模式的匹配项
    // 以此类推
    return $matches[1].($matches[2]+1);
  }
  echo preg_replace_callback(
              "|(/d{2}//d{2}/)(/d{4})|",
              "next_year",
              $text);
  // 结果为:
  // April fools day is 04/01/2003
  // Last christmas was 12/24/2002

这么使用的确没有问题。

但是如果像下面那样在类中调用,就会报错。

//此文本是用于 2002 年的,
//现在想使其能用于 2003 年
$text = "April fools day is 04/01/2002n"; 
$text.= "Last christmas was 12/24/2001n"; 
class ParseDate { 
// 回调函数
function next_year($matches) { 
// 通常:$matches[0] 是完整的匹配项
// $matches[1] 是第一个括号中的子模式的匹配项
// 以此类推
return $matches[1].($matches[2]+1); 
    } 
function displayText($text) { 
echo preg_replace_callback( 
"|(d{2}/d{2}/)(d{4})|", 
"$this->next_year", 
$text); 
    } 
} 
$pt = new ParseText(); 
$pt->displayText($text); 
//此文本是用于 2002 年的,
//现在想使其能用于 2003 年
$text = "April fools day is 04/01/2002n";
$text.= "Last christmas was 12/24/2001n";
class ParseDate {
	// 回调函数
	function next_year($matches) {
		// 通常:$matches[0] 是完整的匹配项
		// $matches[1] 是第一个括号中的子模式的匹配项
		// 以此类推
		return $matches[1].($matches[2]+1);
	}
	function displayText($text) {
		echo preg_replace_callback(
			"|(d{2}/d{2}/)(d{4})|",
			"$this->next_year",
			$text);
	}
}
$pt = new ParseText();
$pt->displayText($text);

上 面的程序执行的结果会是 preg_replace_callback() requires argument 2, […],to be a valid callback 。为什么会这样?让我们再看一次PHP文档对于preg_replace_callback()函数的定义:

mixed preg_replace_callback ( mixed pattern, callback callback, mixed subject [, int limit] )本贴由FastMVC首发,谢谢关注FastMVC。

仔细看第二个参数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(”|(d{2}/d{2}/)(d{4})|”,array( &$this, ‘next_year’), $text);

就应该可以正常运行了。下面是完整的代码。

view plaincopy to clipboardprint?

// 此文本是用于 2002 年的,
// 现在想使其能用于 2003 年
$text = "April fools day is 04/01/2002n"; 
$text.= "Last christmas was 12/24/2001n"; 
class ParseDate { 
// 回调函数
function next_year($matches) { 
// 通常:$matches[0] 是完整的匹配项
// $matches[1] 是第一个括号中的子模式的匹配项
// 以此类推
return $matches[1].($matches[2]+1); 
    } 
function displayText($text) { 
echo preg_replace_callback( 
"|(d{2}/d{2}/)(d{4})|", 
array( &$this, 'next_year'), 
$text); 
    } 
} 
$pt = new ParseText(); 
$pt->displayText($text);

1320