使用正则匹配字符串并替换为Eloquent对象属性值
解决Eloquent模板变量替换时闭包无法访问外部模型的问题
需求说明
有一段包含占位符的模板内容:
Hi my name is {{ client_given_name }} and i live in {{ client_city }}.
同时拥有一个Eloquent模型实例,结构如下:
[ "id" => 12, "given_name" => "John", "family_name" => "DOE", "email" => "john.doe@protonmail.com", "phone_number" => null, "city" => "Paris", "organization_id" => 5485, "created_at" => "2022-07-28 09:29:09", "updated_at" => "2022-07-28 09:29:09" ]
需要将模板中的{{ 变量名 }}替换为模型对应属性的值,最终得到:
Hi my name is John and i live in Paris.
现有代码的问题
你尝试的代码中,闭包无法访问外部的$client变量,这是因为PHP闭包默认不会自动继承外部作用域的变量,必须显式声明要使用的外部变量。另外,代码中仅判断了client_name,和实际模板中的占位符不匹配,也未处理占位符的前缀。
修正后的代码
$client = Client::find(1); $replaced = Str::of($content)->replaceMatches('/\{{\s*(.*?)\s*}}/', function ($match) use ($client) { // 清理占位符内容:去除前后空格和"client_"前缀 $attribute = str_replace('client_', '', trim($match[1])); // 检查模型是否存在该属性,避免访问不存在的属性报错 if ($client->hasAttribute($attribute)) { return $client->$attribute; } // 若属性不存在,返回原占位符(也可根据需求返回空字符串) return $match[0]; });
关键说明
- 闭包访问外部变量:通过
use ($client)语法,将外部的$client模型实例传入闭包,让闭包可以正常访问该变量。 - 处理占位符:正则表达式中加入
\s*,可以匹配占位符前后的空格(比如{{ client_city }}这种格式);通过str_replace去掉client_前缀,匹配模型中的given_name和city属性。 - 安全校验:使用
hasAttribute方法检查模型是否存在目标属性,避免因占位符错误导致的报错,提升代码健壮性。
内容的提问来源于stack exchange,提问作者GotExx
相关产品推荐
相关产品推荐

