在Laravel Blade模板中直接调用json_decode报错:期望参数为字符串,实际传入对象
问题回顾
你在Laravel项目里遇到了一个有点头疼的问题:Result模型对应的results表中,properties是JSON类型字段,在控制器里调用json_decode能正常得到对象或数组,但在Blade模板里直接用{{ json_decode($result->properties) }}就会抛出htmlspecialchars() expects parameter 1 to be string, object given的错误。
问题根源
这其实是Blade语法的默认特性导致的:{{ }}会自动调用PHP的htmlspecialchars()函数转义输出内容,目的是防止XSS攻击。但json_decode()返回的是对象或者数组,并非字符串类型,htmlspecialchars()只能处理字符串,自然就触发了报错。
而你在控制器里用var_dump()是直接输出变量,不会经过Blade的自动转义流程,所以能正常显示解码后的对象/数组。
解决方案(按推荐程度排序)
1. 利用Laravel模型的$casts自动转换JSON字段(最佳实践)
这是最贴合Laravel设计理念的方法,让模型自动帮你处理JSON的序列化和反序列化,完全不用手动调用json_decode。
在你的Result模型里添加$casts属性:
class Result extends Model { // 其他模型代码... protected $casts = [ 'properties' => 'array', // 转成关联数组,也可以用'object'转成对象 ]; }
设置完成后,不管在控制器还是Blade里,直接访问$result->properties就已经是解码后的数组/对象了:
@foreach ($results as $result) {{-- 直接遍历properties里的clubs数组 --}} @foreach ($result->properties['clubs'] as $club) <div>俱乐部名称:{{ $club['name'] }},获胜次数:{{ $club['wins'] }}</div> @endforeach @endforeach
2. 在控制器中提前处理数据再传递给视图
如果暂时不想修改模型,可以在控制器里提前把所有结果的properties解码完成,再传给视图:
public function index() { $user = auth()->user(); $results = Result::getResults($user->properties)->map(function($item) { // 转成关联数组,true参数控制返回类型 $item->properties = json_decode($item->properties, true); return $item; }); return view('dashboard', compact('results')); }
之后在Blade里就可以直接使用解码后的$result->properties,用法和上面一致。
3. 绕过Blade的自动转义(仅用于调试或特殊场景)
如果你只是临时想查看解码后的内容,或者需要输出对象/数组的字符串形式,可以用{!! !!}语法绕过自动转义,同时把结果转成字符串:
@foreach ($results as $result) {{-- 输出JSON格式的字符串 --}} {!! json_encode(json_decode($result->properties)) !!} @endforeach
注意:{!! !!}会关闭XSS转义,生产环境使用时一定要确保内容是安全的,避免注入风险。
内容的提问来源于stack exchange,提问作者Zabs

