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; }
问题原因
- Laravel版本差异导致PDO配置不同:Laravel 10默认关闭了
ATTR_STRINGIFY_FETCHES,而Laravel 8未手动配置时,PDO会将所有数据库查询结果转换为字符串。 - 模型未配置类型转换:没有通过
$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
相关产品推荐
相关产品推荐

