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

Laravel API更换主机后JSON返回值数据类型不一致问题解决

解决Laravel API迁移后JSON整数类型差异的问题

这个问题我之前也碰到过,核心原因是PHP/Laravel版本升级后,Eloquent对数据库字段类型的序列化逻辑发生了变化——旧环境下(PHP7.0+旧版Laravel)会把整数类型的数据库字段转成字符串返回,而新环境(PHP7.1+新版Laravel)则会保留原生的整数类型,导致返回的JSON格式出现差异。下面给你几个实用的修复方案:

方案1:使用Laravel模型的$casts属性(推荐)

这是最符合Laravel最佳实践的方式,通过在模型中明确指定字段的输出类型,强制把整数字段转成字符串。

比如在你的Items模型中添加以下代码:

protected $casts = [
    'category_id' => 'string',
    'price' => 'string',
    'is_special_offer' => 'string',
    'status' => 'string',
    // 如果还有其他需要转字符串的整数字段,也可以在这里添加
];

如果Categories模型中的status字段也需要保持字符串格式,同样在Categories模型中添加对应的$casts配置:

protected $casts = [
    'status' => 'string',
];

这样Eloquent在序列化模型数据时,会自动把指定字段转换成字符串类型,不管数据库字段本身是什么类型,返回的JSON格式就能和旧环境保持一致了。

方案2:手动遍历集合转换字段类型

如果不想修改模型,或者只是临时修复特定接口,可以在返回JSON前手动遍历集合,把需要的字段转成字符串:

public function getAllCategories(){
    $info = Categories::with([
        'items' => function($q){
            $q->with(['item_services' => function($qq){
                $qq->with( ['service' => function($qqq){
                    $qqq->select( 'id', 'name', 'image', 'status' );
                }]);
            }])->select( 'id', 'category_id', 'name', 'image', 'price', 'new_price', 'discount', 'discount_description', 'is_special_offer', 'has_merzam', 'has_taneem', 'neela', 'nasha', 'status');
        }])->select('id', 'name', 'image', 'status')->get();

    // 手动转换整数字段为字符串
    $info = $info->map(function($category) {
        // 转换Category模型的status字段
        $category->status = (string)$category->status;
        
        // 转换Items模型的相关字段
        $category->items = $category->items->map(function($item) {
            $item->category_id = (string)$item->category_id;
            $item->price = (string)$item->price;
            $item->is_special_offer = (string)$item->is_special_offer;
            $item->status = (string)$item->status;
            
            // 如果item_services里的service也需要转换status,继续嵌套处理
            $item->item_services = $item->item_services->map(function($service) {
                $service->service->status = (string)$service->service->status;
                return $service;
            });
            
            return $item;
        });
        return $category;
    });

    return response()->json(['status' => true, 'message' => trans('messages.success_message'), 'errors' => [], 'data' => $info]);
}

这种方式比较灵活,但如果字段较多或者关联层级复杂,代码会显得繁琐。

方案3:全局修改JSON序列化行为(谨慎使用)

如果你的所有API接口都需要把整数转成字符串,可以通过自定义响应宏来实现全局转换。在app/Providers/AppServiceProvider.php的boot方法中添加以下代码:

use Illuminate\Support\Facades\Response;

public function boot()
{
    // 定义一个自定义的JSON响应宏,自动把所有整数转成字符串
    Response::macro('jsonWithStringInts', function ($data) {
        $transformed = $this->transformIntsToString($data);
        return response()->json($transformed);
    });
}

// 递归遍历数据,把所有整数转成字符串
private function transformIntsToString($data)
{
    if (is_array($data) || $data instanceof \Illuminate\Support\Collection) {
        foreach ($data as $key => $value) {
            $data[$key] = $this->transformIntsToString($value);
        }
        return $data;
    }
    if (is_int($data)) {
        return (string)$data;
    }
    return $data;
}

然后在接口中使用这个自定义响应宏返回数据:

return response()->jsonWithStringInts(['status' => true, 'message' => trans('messages.success_message'), 'errors' => [], 'data' => $info]);

注意:这个方案会影响所有使用该宏的接口,如果你有部分接口需要保留整数类型,就不太适用了。

内容的提问来源于stack exchange,提问作者Mohammed H. Alghazali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:55:15