preg_replace_callback用于正则匹配后执行自定义回调替换,更安全灵活;回调接收匹配数组,$matches[0]为完整匹配,须返回字符串,支持匿名函数、命名函数及类方法,可use引入外部变量。

PHP 的 preg_replace_callback 用于在正则匹配后,对每个匹配项执行自定义逻辑并返回替换内容,比直接用 preg_replace 配合 e 修饰符(已废弃)更安全、灵活。
回调函数的基本写法
回调函数会自动接收一个数组参数(即匹配结果),其中 $matches[0] 是完整匹配的字符串,$matches[1]、$matches[2] 等是各捕获组的内容。
- 函数可以是匿名函数、命名函数或数组形式的类方法
- 必须返回一个字符串,作为该次匹配的替换结果
- 不返回或返回 null 会被转为空字符串,需注意
示例:把所有数字加括号
$text = '价格是123元,数量是45个';
$result = preg_replace_callback('/\d+/', function ($matches) {
return '(' . $matches[0] . ')';
}, $text);
// 结果:'价格是(123)元,数量是(45)个'
使用命名函数或类方法
适合逻辑较复杂、需要复用或涉及对象状态的情况。
立即学习“PHP免费学习笔记(深入)”;
- 命名函数:
preg_replace_callback($pattern, 'my_handler', $subject) - 静态方法:
preg_replace_callback($pattern, ['MyClass', 'handle'], $subject) - 实例方法:
preg_replace_callback($pattern, [$obj, 'handle'], $subject)
示例:用类方法统一处理不同类型的匹配
class TextFormatter {
public function replaceNumber($matches) {
return '[NUM:' . $matches[0] . ']';
}
public function replaceEmail($matches) {
return '[EMAIL:' . $matches[1] . ']'; // 假设捕获了邮箱前缀
}
}
$formatter = new TextFormatter();
$text = '联系我:123 或 test@example.com';
$result = preg_replace_callback('/\d+/', [$formatter, 'replaceNumber'], $text);
$result = preg_replace_callback('/(\w+)@(\w+\.\w+)/', [$formatter, 'replaceEmail'], $result);
带状态或外部变量的回调(闭包 use)
如果需要在回调中访问外部变量(如计数器、配置、上下文),用 use 关键字导入。
-
use (&$counter)可以传引用,实现累加 -
use ($prefix, $suffix)传值,适合只读配置
示例:给每个匹配编号
$counter = 0;
$text = '苹果 香蕉 苹果';
$result = preg_replace_callback('/苹果/', function ($m) use (&$counter) {
$counter++;
return "苹果[{$counter}]";
}, $text);
// 结果:'苹果[1] 香蕉 苹果[2]'
注意事项和常见坑
实际使用中容易忽略以下细节:
- 回调函数返回值必须是字符串;返回数组、null 或 false 会导致空字符串
- 正则中没加括号(即没定义捕获组),就不要依赖
$matches[1],只用$matches[0] - 多字节字符(如中文)需确保正则使用
u修饰符:/[\x{4e00}-\x{9fff}]+/u - 避免在回调里修改
$matches数组本身,它只是副本,改了也没用



















