📜  Laravel JSON 查询 - PHP (1)

📅  最后修改于: 2023-12-03 15:17:12.795000             🧑  作者: Mango

Laravel JSON 查询 - PHP

在 Laravel 中,我们可以使用 JSON 数据结构来存储和操作数据。Laravel 提供了一些 API 来构建和查询 JSON 数据。本文介绍如何使用这些 API 进行 JSON 查询。

准备工作

在开始查询 JSON 数据之前,我们需要确保有一个包含 JSON 数据的数据库表。假设我们有一个 orders 表,其中包含一个名为 items 的 JSON 字段,它存储了每个订单的商品信息。

为了方便起见,我们可以在 Order 模型中定义一个访问器来获取 items 属性的值:

class Order extends Model
{
    protected $casts = [
        'items' => 'array',
    ];

    public function getItemsAttribute($value)
    {
        return json_decode($value, true);
    }
}

现在,我们可以像访问其他模型属性一样访问 items 属性:

$order = Order::first();

$items = $order->items;

// 获取第一个商品的名称
$name = $items[0]['name'];
基本查询

我们可以使用 where 方法来查询 JSON 数据。以下是一些示例:

// 查找所有包含 "apple" 的订单
$orders = Order::where('items', 'like', '%"name":"apple"%')->get();

// 查找所有包含至少 3 个商品的订单
$orders = Order::whereJsonLength('items', '>=', 3)->get();

// 查找所有包含商品名称是 "apple" 的订单
$orders = Order::whereJsonContains('items->name', 'apple')->get();

// 查找所有包含价格低于 10 的商品的订单
$orders = Order::whereJsonContains('items->price', '<', 10)->get();
whereJsonContains

whereJsonContains 方法用于查找包含特定 JSON 值的记录。它接受两个参数:JSON 键路径和期望的值。键路径可以包含 -> 操作符,用于访问嵌套的 JSON 属性。该方法还支持使用一个数组来查找多个值。

以下是一些示例:

// 查找所有包含商品名称是 "apple" 的订单
$orders = Order::whereJsonContains('items->name', 'apple')->get();

// 查找所有包含商品名称是 "apple" 或者 "banana" 的订单
$orders = Order::whereJsonContains('items->name', ['apple', 'banana'])->get();

// 查找所有包含 "id" 属性为 1 的商品的订单
$orders = Order::whereJsonContains('items->id', 1)->get();

// 查找所有包含 "id" 属性为 1 或者 2 的商品的订单
$orders = Order::whereJsonContains('items->id', [1, 2])->get();
whereJsonLength

whereJsonLength 方法用于查找符合 JSON 值长度条件的记录。它接受三个参数:JSON 键路径、比较符和数字。键路径可以包含 -> 操作符,用于访问嵌套的 JSON 属性。

以下是一些示例:

// 查找所有包含至少 3 个商品的订单
$orders = Order::whereJsonLength('items', '>=', 3)->get();

// 查找所有包含至多 5 个商品的订单
$orders = Order::whereJsonLength('items', '<=', 5)->get();
whereRaw

如果以上方法无法满足您的需求,您可以使用 whereRaw 方法来编写原始的 SQL 表达式。例如,这里是一个使用 JSON_EXTRACT 函数的示例:

// 查找所有包含商品名称是 "apple" 的订单
$orders = Order::whereRaw('JSON_EXTRACT(items, "$[*].name") like ?', ['%apple%'])->get();
高级查询

Laravel 还提供了一些高级查询方法来操作 JSON 数据。

jsonExtract

jsonExtract 方法用于检索嵌套在 JSON 文档中的属性。它接受两个参数:JSON 键路径和别名。键路径可以包含 -> 操作符,用于访问嵌套的 JSON 属性。别名是可选的,用于为返回的列指定别名。

以下是一个使用 jsonExtract 方法的示例:

// 查找所有商品数量大于 2 的订单,只返回商品名称和数量
$orders = Order::select('id', DB::raw('json_extract(items, "$[*].name") as names'), DB::raw('json_extract(items, "$[*].quantity") as quantities'))
    ->whereRaw('json_length(items) > 2')
    ->get();

foreach ($orders as $order) {
    foreach ($order->names as $index => $name) {
        echo "商品名称: $name, 数量: {$order->quantities[$index]} \n";
    }
}
jsonUnquote

jsonUnquote 方法用于删除从 JSON 值中添加的引号。这在处理数字和布尔值时非常有用,因为 JSON 规范要求它们带引号。

以下是一个使用 jsonUnquote 方法的示例:

// 查找所有包含销售价格低于 10 的商品的订单
$orders = Order::select('id', 'items')
    ->whereRaw('json_unquote(json_extract(items, "$[*].sale_price")) < 10')
    ->get();
jsonSet

jsonSet 方法用于将新属性设置到现有的 JSON 文档中。它接受三个参数:JSON 键路径、新值和是否覆盖现有值。

以下是一个使用 jsonSet 方法的示例:

// 将订单中第 2 个商品的库存设置为 0
$order = Order::first();

$json = collect($order->items)->map(function ($item, $index) {
    if ($index == 1) {
        $item['stock'] = 0;
    }

    return $item;
})->toJson();

$order->update(['items' => $json]);
jsonMerge

jsonMerge 方法用于将多个 JSON 文档合并成一个。它接受一个包含多个 JSON 文档的数组。

以下是一个使用 jsonMerge 方法的示例:

// 将两个订单中的商品进行合并
$orders = Order::whereIn('id', [1, 2])->get();

$json = $orders->pluck('items')->reduce(function ($carry, $items) {
    return array_merge_recursive($carry, json_decode($items, true));
}, []);

$json = json_encode($json);

$mergedOrder = new Order(['items' => $json]);
$mergedOrder->save();
结语

这就是 Laravel 中 JSON 查询的基础知识。如果您想深入了解,请查阅 Laravel 文档中的相关章节。