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

Laravel批量更新数据时报错及代码优化咨询

问题1:批量更新报错修复

报错原因

报错信息显示cash字段为整数类型,但你传入了数组[10000,10000],Laravel将数组转为字符串后不符合SQL整数格式要求,导致数据库抛出类型错误。核心问题是:Laravel的update()方法接收的是键值对,值必须是单个合法值,不能直接用数组批量更新多条记录的对应字段。

修复方案

替换原更新逻辑,循环处理每条需要更新的记录(更直观适配当前场景):

原错误代码:

if ($kriya->pluck('school_id') == $budget_data->pluck('school_id')) {
    Palika_ToSchool_Kriyakalap::whereIn('kriya_name', $budget_data->pluck('kriyakalap'))
        ->whereIn('school_id', $budget_data->pluck('school_id'))
        ->update(['cash' => $newArray]);
}

改为:

// 检查是否存在需要更新的记录
if ($kriya->isNotEmpty()) {
    // 遍历每条记录,对应更新cash值
    foreach ($kriya as $index => $item) {
        $item->update([
            'cash' => $newArray[$index]
        ]);
    }
}

注:原判断条件$kriya->pluck('school_id') == $budget_data->pluck('school_id')逻辑不准确,集合直接用==比较可能不符合预期,改为检查$kriya是否非空即可。

问题2:代码优化与编码技能提升

现有代码的明显问题

  1. 重复冗余查询:$budget_data中重复写了两次where('biniyojan_id', $biniyojan_id);$budget_cash的查询可合并到$budget_data中,避免重复访问数据库。
  2. 变量命名错误:$upudate拼写错误,应为$update。
  3. 插入逻辑错误:Palika_ToSchool_Kriyakalap::where('kriya_name' != $bud->kriyakalap)->insert($data)写法违规,正确格式是where('kriya_name', '!=', $bud->kriyakalap),且该逻辑未判断记录是否存在,可能导致重复插入。
  4. 控制器臃肿:所有业务逻辑堆在控制器方法中,违反单一职责原则,后期维护难度大。

优化建议

1. 使用Laravel Upsert简化逻辑

Laravel提供upsert()方法,专门处理「存在则更新,不存在则插入」的场景,大幅简化代码:

// 整理需要批量处理的数据
$upsertData = $budget_data->map(function ($bud) {
    // 获取现有记录的cash值,无则默认为0
    $existingCash = Palika_ToSchool_Kriyakalap::where('school_id', $bud->school_id)
        ->where('kriya_name', $bud->kriyakalap)
        ->value('cash') ?: 0;
    
    return [
        'school_id' => $bud->school_id,
        'kriya_name' => $bud->kriyakalap,
        'cash' => $existingCash + $bud->cash,
        'created_at' => now(),
        'updated_at' => now()
    ];
})->toArray();

// 执行upsert:第二个参数是联合唯一索引(用于判断记录是否存在),第三个参数是需要更新的字段
Palika_ToSchool_Kriyakalap::upsert(
    $upsertData,
    ['school_id', 'kriya_name'],
    ['cash', 'updated_at']
);

注:需在palika_to_school_kriyakalap表中给school_id和kriya_name添加联合唯一索引,否则upsert无法正常工作。

2. 抽离业务逻辑到模型

将业务逻辑从控制器中分离,放到Palika_ToSchool_Kriyakalap模型中:

// Palika_ToSchool_Kriyakalap.php 模型文件
public static function syncFromBiniyojan($biniyojanId)
{
    $budgetData = BiniyojanDetails::where('biniyojan_id', $biniyojanId)->get();
    
    $upsertData = $budgetData->map(function ($bud) {
        $existingCash = self::where('school_id', $bud->school_id)
            ->where('kriya_name', $bud->kriyakalap)
            ->value('cash') ?: 0;
        
        return [
            'school_id' => $bud->school_id,
            'kriya_name' => $bud->kriyakalap,
            'cash' => $existingCash + $bud->cash,
            'created_at' => now(),
            'updated_at' => now()
        ];
    })->toArray();
    
    return self::upsert(
        $upsertData,
        ['school_id', 'kriya_name'],
        ['cash', 'updated_at']
    );
}

控制器代码简化为:

public function approve(Request $request, $biniyojan_id)
{
    $update = DB::table('biniyojan')
        ->where('biniyojan_id', $biniyojan_id)
        ->update(['biniyojan_status' => 1]);

    if ($update) {
        Palika_ToSchool_Kriyakalap::syncFromBiniyojan($biniyojan_id);
        return redirect()->back()->with('status', 'Approved!!!');
    }
    
    return redirect()->back()->with('error', 'Error!!!');
}

3. 添加事务保证数据一致性

确保更新biniyojan状态和同步数据的操作要么全部成功,要么全部回滚:

use Illuminate\Support\Facades\DB;

public function approve(Request $request, $biniyojan_id)
{
    DB::beginTransaction();
    try {
        $update = DB::table('biniyojan')
            ->where('biniyojan_id', $biniyojan_id)
            ->update(['biniyojan_status' => 1]);

        if (!$update) {
            throw new \Exception('Failed to update biniyojan status');
        }

        Palika_ToSchool_Kriyakalap::syncFromBiniyojan($biniyojan_id);
        
        DB::commit();
        return redirect()->back()->with('status', 'Approved!!!');
    } catch (\Exception $e) {
        DB::rollBack();
        return redirect()->back()->with('error', 'Error!!!');
    }
}

编码技能提升方向

  • 吃透Eloquent ORM:熟练掌握关联关系、查询构造器、批量操作等功能,减少重复代码。
  • 遵循SOLID原则:控制器只处理请求和响应,业务逻辑交给模型或服务类。
  • 严格代码规范:遵循PSR-12命名规范,变量名清晰易懂,添加必要注释。
  • 掌握调试技巧:用Log::info()输出中间变量,或dd()调试数据集合,高效排查问题。
  • 学习数据库优化:合理添加索引,减少不必要的查询,提升系统性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 10:00:55