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

Laravel中如何在工厂生成合法JSON以通过PHPUnit验证?

解决Laravel工厂生成JSON数据无法通过验证的问题

问题根源

核心矛盾在于模型字段转换和验证规则的不匹配:

  • 模型中$casts = ['settings' => 'array']会自动将赋值的JSON字符串转为数组,或把数组转为JSON字符串存储到数据库。
  • 测试中用make()创建模型实例后调用toArray(),settings会以数组形式输出,但控制器验证规则要求的是JSON格式的字符串,导致验证失败。
  • 另外,工厂中name字段使用$this->faker->words(3,7)返回的是数组,不符合name字段string的验证规则,这也是潜在问题。

解决方案

方案1:使用工厂raw()方法获取原始数据

raw()方法直接返回工厂定义的原始数组,不会经过模型的字段转换处理,确保settings是JSON字符串格式:

  1. 修正工厂代码(同时修复name字段的问题):
class ExampleFactory extends Factory
{
    protected $model = Example::class;

    public function definition()
    {
        return [
            'name' => $this->faker->sentence(3), // 返回字符串,符合验证规则
            'settings' => json_encode(['areas' => ['full', 'city']])
        ];
    }
}
  1. 修改测试代码,使用raw()获取数据:
/** @test */
public function shouldStore(): void
{
    $data = $this->model::factory()->raw();
    $this->post(action([$this->controller, 'store']), $data)
        ->assertOk();
}

方案2:测试中手动转换settings为JSON字符串

如果仍想使用make()方法,可在转换数组后手动将settings重新编码为JSON字符串:

  1. 工厂中直接使用数组定义settings(更直观):
public function definition()
{
    return [
        'name' => $this->faker->sentence(3),
        'settings' => ['areas' => ['full', 'city']]
    ];
}
  1. 测试中处理数据:
/** @test */
public function shouldStore(): void
{
    $item = $this->model::factory()->make();
    $data = $item->toArray();
    $data['settings'] = json_encode($data['settings']); // 将数组转回JSON字符串
    $this->post(action([$this->controller, 'store']), $data)
        ->assertOk();
}

方案3:调整验证规则为array(业务允许时)

如果业务支持前端提交数组格式的settings,可以修改模型的验证规则,让数组和JSON字符串都能通过验证(Laravel会自动解析JSON字符串为数组):

public static $rules = [
    'name' => 'required|string|max:255',
    'settings' => 'nullable|array'
];

此时工厂中直接用数组定义settings,测试中toArray()后的数组能直接通过验证,模型的cast会自动将其转为JSON字符串存储。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 18:41:06