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

Laravel 5.6如何测试JSON/JSONb列?assertDatabaseHas失效处理

解决Laravel 5.6中测试完整JSON/JSONb列的问题

嘿,我之前在Laravel 5.6里也碰到过类似的困扰,这个版本对JSON列的断言支持确实不如后续版本灵活,不过有几个实用的办法能帮你一次性检查完整的JSON内容:

方法一:利用模型的类型转换(最简洁)

如果你的Eloquent模型已经给JSON列设置了类型转换,比如:

class YourModel extends Model
{
    protected $casts = [
        'options' => 'array', // 自动把JSON列转为PHP数组
    ];
}

那你完全可以直接通过模型实例来断言,不需要绕到数据库操作:

// 先执行你的store动作,比如创建模型
$model = $this->post('/your-store-route', $yourRequestData);

// 定义预期的完整JSON数组(包含所有元数据)
$expectedOptions = [
    'language' => 'en',
    'theme' => 'dark',
    'notifications' => ['email' => true, 'push' => false],
    // 其他所有需要检查的字段
];

// 直接对比模型的属性即可
$this->assertEquals($expectedOptions, $model->options);

这种方式最直观,Laravel会自动帮你把数据库里的JSON字符串解码成数组,省去手动处理的麻烦。

方法二:手动查询数据库并解码对比

如果因为某些原因不能直接用模型实例(比如测试的是纯数据库操作),可以手动查询后解码对比:

// 执行store动作后,假设你知道目标记录的ID
$targetRecordId = 1;

$expectedOptions = [/* 你的完整JSON数组 */];

// 查询记录并解码JSON列
$record = DB::table('your_table')->find($targetRecordId);
$actualOptions = json_decode($record->options, true);

// 对比完整数组
$this->assertEquals($expectedOptions, $actualOptions);

如果JSON的键顺序可能不一致(比如前端传参顺序和数据库存储不同),可以用assertArraySubset忽略顺序只检查键值对(Laravel 5.6支持这个方法):

$this->assertArraySubset($expectedOptions, $actualOptions);

方法三:使用原生SQL条件断言存在

如果你坚持想用assertDatabaseHas,可以通过原生SQL的方式做JSON精确匹配,不同数据库语法略有区别:

针对MySQL:

$this->assertDatabaseHas('your_table', [
    'id' => $targetRecordId,
    DB::raw('options = ?') => json_encode($expectedOptions)
]);

针对PostgreSQL(JSONb类型):

$this->assertDatabaseHas('your_table', [
    'id' => $targetRecordId,
    DB::raw('options = ?::jsonb') => json_encode($expectedOptions)
]);

这种方式直接让数据库完成JSON的匹配校验,适合不需要解码到PHP数组的场景。


内容的提问来源于stack exchange,提问作者D.R.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:41:41