You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 6中嵌套JSON数组的存储与特定节点数据检索问题

解决Laravel中嵌套JSON字段的数据查询与提取问题

看起来你在处理多层嵌套的JSON数据时遇到了瓶颈,别着急,我们一步步拆解问题来解决它。

首先,先理清你的数据结构:add_ons是一个嵌套了多层数组的JSON字段,要定位到whiteOne的价格,需要分两步走:正确筛选出目标记录,再从记录中提取深层嵌套的值。


一、修复你的查询语句

你之前用的Item::whereJsonContains('add_ons->data->name','sauces')->get()无法正确匹配,核心原因是data是一个数组,你需要明确告诉MySQL去检查数组内的所有元素,而不是直接访问data->name。正确的写法应该是:

// 筛选出add_ons.data数组中存在name为"sauces"的记录
$items = Item::whereJsonContains('add_ons->data[*]->name', 'sauces')->get();

如果要更精准地筛选出包含whiteOne的记录,可以用多层数组的路径匹配:

// 筛选出所有包含whiteOne的Item记录
$items = Item::whereJsonContains('add_ons->data[*]->type[*]->type[*]->name', 'whiteOne')->get();

如果你的MySQL版本对[*]语法支持有限,也可以用whereRaw结合原生JSON函数实现:

$items = Item::whereRaw('JSON_CONTAINS(add_ons->"$.data[*].type[*].type[*].name", \'"whiteOne"\')')->get();

二、提取目标价格值

当你拿到目标记录(比如用find(16)获取特定Item)后,Laravel会自动将JSON字段转换为数组,你可以逐层访问嵌套结构:

$item = Item::find(16);

// 逐层访问:先拿到data数组的第一个sauces项
$sauceGroup = $item->add_ons['data'][0];
// 拿到type数组中的"white sauce"项
$whiteSauce = $sauceGroup['type'][0];
// 从white sauce的子type数组中找到whiteOne的价格
$whiteOnePrice = collect($whiteSauce['type'])->firstWhere('name', 'whiteOne')['price'];

// 输出结果:10
echo $whiteOnePrice;

如果担心数组索引的不确定性(比如data里可能有多个元素),可以用集合方法做更安全的查找:

$item = Item::find(16);

// 先找到data中name为sauces的项
$sauceGroup = collect($item->add_ons['data'])->firstWhere('name', 'sauces');

if ($sauceGroup) {
    // 找到type中name为white sauce的项
    $whiteSauce = collect($sauceGroup['type'])->firstWhere('name', 'white sauce');
    
    if ($whiteSauce) {
        // 提取whiteOne的价格
        $whiteOnePrice = collect($whiteSauce['type'])->firstWhere('name', 'whiteOne')['price'];
        echo $whiteOnePrice;
    }
}

这种方式更健壮,即使JSON结构中数组元素顺序变化,也能正确定位目标值。


三、优化小技巧

如果你需要频繁访问这类深层嵌套的值,可以在Item模型中定义访问器,简化后续代码:

// 在app/Models/Item.php中添加访问器
public function getWhiteOnePriceAttribute()
{
    $sauceGroup = collect($this->add_ons['data'])->firstWhere('name', 'sauces');
    if (!$sauceGroup) return null;
    
    $whiteSauce = collect($sauceGroup['type'])->firstWhere('name', 'white sauce');
    if (!$whiteSauce) return null;
    
    $whiteOne = collect($whiteSauce['type'])->firstWhere('name', 'whiteOne');
    return $whiteOne ? $whiteOne['price'] : null;
}

之后你就可以直接用$item->white_one_price快速获取价格,非常便捷!

内容的提问来源于stack exchange,提问作者Debu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 18:07:47