CodeIgniter+MySQL如何实现新增商品、编辑更新购物车订单
CodeIgniter 购物车订单编辑功能问题修复
原代码核心缺陷
- 判断逻辑维度错误:仅通过外键
oid判断订单明细是否存在,未关联商品IDp_id,只要订单存在任意一条明细,后续所有商品都会触发更新逻辑,最终订单明细会被最后一条遍历的商品覆盖,造成数据丢失 - 性能冗余:循环内重复查询当前订单的明细总数,无意义消耗数据库资源
- 更新条件缺失:更新操作仅添加
oid过滤条件,会将订单下所有商品明细全部修改为当前遍历的商品数据 - 逻辑冗余:插入分支重复调用
set()方法设置oid,该字段已经包含在待插入的数组中 - 格式错误:时间格式使用12小时制的
h参数,订单场景需使用24小时制的H参数 - 数据风险:未判断商品是否已存在于当前订单,会出现同一商品重复生成多条明细的脏数据
修正后实现代码
// 提前一次性查询当前订单已存在的商品ID,避免循环内重复查库 $existing_records = $this->db->select('p_id') ->where('oid', $id) ->get('order_details') ->result_array(); $existing_pids = array_column($existing_records, 'p_id'); if ($cart = $this->cart->contents()) { // 开启事务保证数据一致性 $this->db->trans_start(); foreach ($cart as $item) { $detail = [ 'oid' => $id, 'p_id' => $item['id'], 'qty' => $item['qty'], 'price' => $item['price'], 'total_amnt' => $item['qty'] * $item['price'] ]; if (in_array($item['id'], $existing_pids)) { // 必须同时用订单ID+商品ID定位单条明细,避免误更新 $this->db->where('oid', $id) ->where('p_id', $item['id']) ->update('order_details', $detail); } else { // 新插入记录才设置创建时间 $detail['created_at'] = date('Y-m-d H:i:s'); $this->db->insert('order_details', $detail); } } // 可选:如果要求订单明细与购物车完全同步,删除购物车中已移除的旧商品明细 $current_cart_pids = array_column($cart, 'id'); $need_delete = array_diff($existing_pids, $current_cart_pids); if (!empty($need_delete)) { $this->db->where('oid', $id) ->where_in('p_id', $need_delete) ->delete('order_details'); } $this->db->trans_complete(); }
优化建议
- 数据库层给
order_details表添加(oid, p_id)联合唯一索引,从底层避免同一订单下出现重复商品的脏数据;加索引后可直接使用MySQL的ON DUPLICATE KEY UPDATE语法,省略提前查询的步骤,代码更简洁 - 所有明细操作完成后,记得重新汇总所有商品的
total_amnt,更新订单主表的总金额字段,避免主表和明细表金额不一致 - 涉及多表更新、多行写入的场景必须开启事务,避免中途报错导致部分数据更新成功、部分失败的数据不一致问题
内容的提问来源于stack exchange,提问作者Tech Image
相关产品推荐
相关产品推荐

