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

Laravel8 循环迭代中保存Model仅第一条数据生效如何解决

问题修复方案

核心错误原因

  • 循环内提前返回:你的return $result;语句写在了for循环内部,第一次遍历手机号执行完充值逻辑后,就会直接终止程序返回结果,后续的手机号遍历逻辑完全不会执行,这是仅第一个手机号能保存的核心原因。
  • 其他潜在错误:
    • Msisdn::create() 传参格式错误:数组第一个元素是无键的字符串'requestType',不符合模型字段赋值的键值对要求,会导致数据写入异常。
    • 调用virtual_recharge方法时,$customerMsisdn、$transactionDescription两个变量未定义,运行时会抛出变量未定义的错误。
    • 余额校验逻辑错误:原判断公式($amount * count($phones))-$amount少算了单份金额,比如3个手机号每个5元总消耗应为15元,原公式计算结果为10元,会导致余额校验逻辑失效。
    • 每次循环都重复查询、更新余额表,会产生不必要的数据库IO,也存在并发扣减的安全隐患。

修复后代码参考

$product = $request->product;
$float = Balance::where('user_id', Auth::user()->id)->first();
$bundleId = $request->bundle;

if(is_null($product)){
    return "Please select product";
}else if($product ==1){//airtime
    $amount = $request->amount;
    $airtimePhoneNumbers = $request->airtimePhoneNumbers;
    $resultList = []; // 收集所有手机号的充值结果

    if(str_contains($airtimePhoneNumbers, ';')){
        $phones = explode(';', $airtimePhoneNumbers);
        $totalAmount = $amount * count($phones);
        // 修正余额校验逻辑
        if($float->float < $totalAmount){
            return 'Not enough float to perfom this operation';
        }else{
            foreach ($phones as $phone) {
                $rsn = mt_rand(100000000, 999999999);
                $sessionToken =(string) Str::uuid();
                $transactionDescription = 'descripti1on';

                Msisdn::create([
                    'requestType' => 0, // 补上缺失的键值对
                    'product'=>$product,
                    'amount' => $amount,
                    'sessionToken'=>$sessionToken,
                    'bundleId'=>'airtime',
                    'rsn'=>$rsn,
                    'customerMsisdn'=>$phone,
                    'trxnDescription'=>$transactionDescription,
                ]);

                // 调用充值接口,补上缺失的变量
                $result = $this->asapCore->virtual_recharge($amount, $sessionToken, $rsn, $phone, $transactionDescription, $requestType = 0);
                $resultList[] = [
                    'phone' => $phone,
                    'result' => $result
                ];
            }
            // 循环结束后统一扣减余额
            $float->float = $float->float - $totalAmount;
            $float->save();
            // 所有手机号处理完成后再统一返回结果
            return $resultList;
        }
    }else{
        // 单手机号处理逻辑
    }
}

额外优化建议

如果担心充值过程中出现异常导致部分成功部分失败,可以引入数据库事务,保证数据一致性:所有手机号写入和余额扣减要么全部成功,要么全部回滚。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 17:45:01