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

Laravel 10降级到8后JSON响应字段类型不符求助

Laravel 8降级后JSON响应字段类型不匹配问题解决

问题重现

将Laravel从10版本降级到8版本后,接口返回的JSON响应中,除id外的所有字段都被序列化为字符串类型,例如:

  • 迁移中定义为unsignedBigInteger的user_id返回"3"
  • decimal类型的total_amount返回"16980"
  • boolean类型的paid返回"0"

响应示例:

{
    "res": {
        "id": 5,
        "user_id": "3",
        "shipping_method": "standard",
        "order_date": "2023/07/06",
        "total_amount": "16980",
        "status": "validation",
        "paid": "0",
        "created_at": "2023-07-06T22:32:31.000000Z",
        "updated_at": "2023-07-06T22:32:32.000000Z",
        "rating": "0",
        "items": [...]
    }
}

对应的迁移代码:

Schema::create('orders', function (Blueprint $table) {
    $table->id();
    $table->unsignedBigInteger('user_id');
    $table->string('shipping_method');
    $table->date('order_date');
    $table->decimal('total_amount', 10, 2);
    $table->string('status');
    $table->boolean('paid');
    $table->timestamps();

    $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});

原查询代码:

public function index($userId)
{
    $orders = Order::where('user_id', '=',  $userId )->get();
    foreach ($orders as $o){
        $items=$o->items;
        foreach ($items as $i){
            $productId=$i->product_id;
            $product=Product::find($productId);
            $i->product=$product;
        }
    }
    return $orders;
}

问题原因

  1. Laravel版本差异导致PDO配置不同:Laravel 10默认关闭了ATTR_STRINGIFY_FETCHES,而Laravel 8未手动配置时,PDO会将所有数据库查询结果转换为字符串。
  2. 模型未配置类型转换:没有通过$casts属性明确指定字段类型,Laravel序列化时无法自动匹配迁移定义的类型。

解决方案

1. 修正数据库PDO配置

修改config/database.php中的MySQL连接配置,关闭字符串化结果并开启严格模式:

'mysql' => [
    // 保留原有配置
    'strict' => true,
    'options' => extension_loaded('pdo_mysql') ? array_filter([
        PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
        PDO::ATTR_STRINGIFY_FETCHES => false, // 禁止将所有结果转为字符串
        PDO::ATTR_EMULATE_PREPARES => false, // 禁用预处理语句模拟,保证类型正确
    ]) : [],
],

2. 在Order模型中添加类型转换

在Order模型中定义$casts属性,强制指定字段的序列化类型:

class Order extends Model
{
    // 其他模型代码...
    
    protected $casts = [
        'user_id' => 'integer',
        'order_date' => 'date',
        'total_amount' => 'decimal:2',
        'paid' => 'boolean',
        'rating' => 'integer', // 根据响应补充的字段类型
    ];
}

如果Item和Product模型也存在类似类型问题,同样需要为它们添加对应的$casts配置。

3. 优化查询避免N+1问题(可选但推荐)

原查询中循环查询Product会导致N+1性能问题,改用预加载关联模型,同时保证关联字段类型正确:

public function index($userId)
{
    $orders = Order::with('items.product')
        ->where('user_id', $userId)
        ->get();
    
    return $orders;
}

完成以上配置后,重新请求接口,JSON响应中的字段类型就会与迁移定义的类型一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 16:37:11