0

0

如何在Laravel中高效查询和更新JSON字段? (箭头语法与whereJsonContains)

冰火之心

冰火之心

发布时间:2026-01-15 08:43:02

|

705人浏览过

|

来源于php中文网

原创

必须使用 whereJsonContains 查询 JSON 字段,因其底层调用数据库原生 JSON 查询函数(如 MySQL 的 JSON_CONTAINS、PostgreSQL 的 @>),确保结构化匹配;而 where 方法仅作字符串模糊匹配,不安全且不可靠。

如何在laravel中高效查询和更新json字段? (箭头语法与wherejsoncontains)

JSON字段查询必须用 whereJsonContains,不能用 where 直接比较

MySQL 5.7+ 和 PostgreSQL 原生支持 JSON 字段,但 Laravel 的 where 方法对 JSON 列执行的是字符串级模糊匹配,不是结构化查询。比如字段 meta 存了 {"tags": ["php", "laravel"]},写 where('meta', 'like', '%laravel%') 可能误中其他字段或被转义干扰。

whereJsonContains 才是语义正确的选择,它底层调用数据库的 JSON_CONTAINS(MySQL)或 @>(PostgreSQL),确保只匹配到 JSON 数组中的值或对象中的键值对

  • 数组场景:查含某个 tag → whereJsonContains('meta->tags', 'laravel')
  • 对象场景:查 status 为 active → whereJsonContains('meta', ['status' => 'active'])
  • 注意:第二个参数必须是 PHP 数组或标量;传 JSON 字符串会失败

-> 箭头语法只适用于 SELECT 和 UPDATE,不能用于 WHERE 条件中的路径计算

Laravel 的 -> 是 Eloquent 对 JSON 字段的“虚拟列”映射语法,仅在读取(select)、更新(update)和部分写入(json_set)时生效。它不参与 SQL 的 WHERE 解析逻辑 —— 换句话说,where('meta->tags', 'laravel') 实际发出去的是字符串比较,不是 JSON 查询。

真正安全的写法是显式使用 whereJsonContainswhereJsonLength 等专用方法。如果真要按路径做等值判断(如确定某个 key 的值完全等于某字符串),可用 whereRaw 配合数据库函数:

->whereRaw("JSON_UNQUOTE(JSON_EXTRACT(meta, '$.tags[0]')) = ?", ['php'])

但这种写法失去可移植性,且无法利用 JSON 索引(除非你手动建了生成列 + 索引)。

更新 JSON 字段要用 json_set 或模型属性赋值,避免全量覆盖

直接给 JSON 字段赋整个新数组(如 $model->meta = ['tags' => ['js']])会导致其他未提及的 key(比如 authorpublished_at)被清空。正确做法分两种:

  • 局部更新(推荐):用数据库原生函数 json_set,例如
DB::table('posts')
    ->where('id', 1)
    ->update([
        'meta' => DB::raw("JSON_SET(meta, '$.tags', JSON_MERGE_PATCH(JSON_EXTRACT(meta, '$.tags'), '["vue"]'))")
    ])
  • 模型方式:先取再改再存,适合逻辑简单、并发低的场景
$post = Post::find(1);
$tags = $post->meta->tags ?? [];
$tags[] = 'vue';
$post->meta->tags = $tags;
$post->save();

注意:Eloquent 会把 $post->meta 当作 stdClass 或数组(取决于 casts 配置),但修改后保存仍是全量写入 —— 所以仅当确认没有其他并行写入时才用这种方式。

性能关键:JSON 字段必须配合生成列 + 索引,否则 whereJsonContains 很慢

MySQL 的 JSON_CONTAINS 默认无法走索引,即使字段加了普通 B-tree 索引也没用。必须额外创建一个生成列(generated column),再对其建索引:

ALTER TABLE posts ADD COLUMN tags_json JSON AS (meta->'$.tags');
ALTER TABLE posts ADD INDEX idx_tags_json (tags_json);

之后 whereJsonContains('meta->tags', 'laravel') 才可能命中索引。PostgreSQL 同理,需用 jsonb_path_ops 索引:

CREATE INDEX CONCURRENTLY idx_posts_meta_tags ON posts USING GIN ((meta->'tags')); 

没建对应索引时,千万条数据上 whereJsonContains 可能秒变全表扫描。这个步骤常被跳过,却是线上慢查的根源之一。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2525

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1603

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1496

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

952

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1416

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1234

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1445

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1306

2023.11.13

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

36

2026.01.14

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 1.8万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 793人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号