本文详解如何将 laravel 查询结果(collection)转换为嵌套结构的 json 数据,用于前端 javascript 级联下拉菜单(如品类 → 子类 → 型号),并解决 blade 模板中安全输出 json 的关键问题。
在构建多级联动选择器(例如「分类 → 子分类 → 具体型号」)时,后端需提供结构清晰、可直接被 JavaScript 解析的嵌套 JSON 数据。Laravel 的集合(Collection)提供了强大而简洁的链式方法,可高效完成从数据库原始结果到目标 JSON 的转换。
假设你已通过 Eloquent 或 Query Builder 获取了去重且字段完整的数据:
$collection = DB::table('products')
->select('category', 'sub_category', 'model')
->whereNotNull('category')
->whereNotNull('sub_category')
->whereNotNull('model')
->distinct()
->get();接下来,使用 Collection 方法逐层分组与提取:
$jsonData = $collection
->groupBy('category') // 第一层:按 category 分组
->map(function ($byCategory) {
return $byCategory
->groupBy('sub_category') // 第二层:每个 category 内按 sub_category 分组
->map(function ($bySubCategory) {
return $bySubCategory->pluck('model')->values(); // 提取所有 model 并重置索引
})
->toArray(); // 转为关联数组,确保 JSON 键名保留
})
->toJson(JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);? 关键点说明:->values() 确保模型列表为纯数字索引数组(避免 JSON 中出现冗余键);JSON_UNESCAPED_UNICODE 防止中文被转义为 \uXXXX;JSON_PRETTY_PRINT 仅用于调试,生产环境建议省略以减小体积。
❌ 错误写法(XSS 风险 + 语法错误):
var subjectObject = "{{ $jsonData }}"; // 字符串包裹导致 JS 解析失败,且未转义✅ 正确写法(推荐):
? @json() 是 Laravel 5.5+ 提供的安全辅助指令,它等价于 json_encode($data, JSON_UNESCAPED_UNICODE) 并自动适配 HTML/JS 上下文,无需手动 htmlspecialchars 或双花括号插值。
Controller:
public function index()
{
$jsonData = Product::select('category', 'sub_category', 'model')
->whereNotNull('category')
->whereNotNull('sub_category')
->whereNotNull('model')
->distinct()
->get()
->groupBy('category')
->map(fn($items) => $items
->groupBy('sub_category')
->map(fn($subs) => $subs->pluck('model')->values())
->toArray()
)
->toJson(JSON_UNESCAPED_UNICODE);
return view('products.index', compact('jsonData'));
}Blade (resources/views/products/index.blade.php):
通过以上方式,你即可获得结构规范、语
