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

CodeIgniter多表数据操作异常:用户表正常,凭证表报错

问题分析与解决方案

先梳理下你的场景:你在CodeIgniter项目中编辑用户信息时,希望同步更新voucher表的状态(对应paid/unpaid按钮),目前ci_users表的更新操作正常,但涉及voucher表时出现报错。结合你提供的代码和表结构,我从几个关键点帮你排查和修正:


1. 核心问题:控制器未调用voucher表的更新逻辑

看你当前的edit方法,仅执行了ci_users表的更新,完全没有处理voucher表的同步操作。这是导致voucher状态没变化甚至报错的首要原因——你需要在用户信息更新成功后,添加voucher表的更新/创建逻辑。


2. 模型代码的潜在优化点

时间格式错误

你代码中使用了date('Y-m-d : h:m:s'),这里的多余冒号和12小时制的h是不规范的,建议统一使用标准的Y-m-d H:i:s格式(24小时制)。

操作结果判断不严谨

原方法直接返回true,但实际可能因为WHERE条件不匹配导致更新0行,建议用$this->db->affected_rows() > 0来判断操作是否真的成功。

优化后的模型代码:

// Get user detail by ID
public function get_user_by_id($id){
    $query = $this->db->get_where('ci_users', array('id' => $id));
    return $query->row_array();
}

//---------------------------------------------------
// Edit user Record
public function edit_user($data, $id){
    $this->db->where('id', $id);
    // 修正时间格式
    if(isset($data['updated_at'])){
        $data['updated_at'] = date('Y-m-d H:i:s');
    }
    $this->db->update('ci_users', $data);
    // 返回实际是否更新成功
    return $this->db->affected_rows() > 0;
}

//---------------------------------------------------
// Get User Role/Group
public function get_user_groups(){
    $query = $this->db->get('ci_user_groups');
    return $query->result_array();
}

// Get voucher detail by Mobile No
public function get_voucher_by_mobile_no($mobile_no){
    $query = $this->db->get_where('voucher', array('mobile_no' => $mobile_no));
    return $query->row_array();
}

// Edit voucher Record
public function update_voucher_by_mobile($data, $mobile_no){
    $this->db->where('mobile_no', $mobile_no);
    if(isset($data['updated_at'])){
        $data['updated_at'] = date('Y-m-d H:i:s');
    }
    $this->db->update('voucher', $data);
    return $this->db->affected_rows() > 0;
}

3. 修正后的控制器逻辑

在用户信息更新成功后,添加voucher表的处理逻辑:检查是否存在对应手机号的voucher记录,存在则更新状态,不存在可选择创建新记录(根据你的业务需求)。

public function edit($id = 0){
    if($this->input->post('submit')){
        $this->form_validation->set_rules('username', 'Username', 'trim|required');
        $this->form_validation->set_rules('firstname', 'Firstname', 'trim|required');
        $this->form_validation->set_rules('lastname', 'Lastname', 'trim|required');
        $this->form_validation->set_rules('email', 'Email', 'trim|valid_email|required');
        $this->form_validation->set_rules('mobile_no', 'Number', 'trim|required');
        $this->form_validation->set_rules('status', 'Status', 'trim|required');
        $this->form_validation->set_rules('address', 'Address', 'trim');
        $this->form_validation->set_rules('group', 'Group', 'trim|required');
        // 建议添加voucher状态的验证(如果表单中有这个字段)
        // $this->form_validation->set_rules('voucher_status', 'Voucher Status', 'trim|required');

        if ($this->form_validation->run() == FALSE) {
            $data['user'] = $this->user_working->get_user_by_id($id);
            $data['user_groups'] = $this->user_working->get_user_groups();
            $data['view'] = 'user/users/user_edit';
            $this->load->view('layout', $data);
        } else{
            $user_info = $this->user_working->get_user_by_id($id);
            $data = array(
                'referred_by_id' => $this->session->userdata('referred_by_id'),
                'name' => $this->session->userdata('sponcer_name'),
                'username' => $this->input->post('username'),
                'firstname' => $this->input->post('firstname'),
                'lastname' => $this->input->post('lastname'),
                'email' => $this->input->post('email'),
                'mobile_no' => $this->input->post('mobile_no'),
                // 注意:只有当用户提交了新密码时才更新,否则保留原密码
                'password' => !empty($this->input->post('password')) ? password_hash($this->input->post('password'), PASSWORD_BCRYPT) : $user_info['password'],
                'role' => $this->input->post('group'),
                'address' => $this->input->post('address'),
                'is_active' => $this->input->post('status'),
                'updated_at' => date('Y-m-d H:i:s'),
            );
            $data = $this->security->xss_clean($data);
            $result = $this->user_working->edit_user($data, $id);

            if($result){
                $mobile_no = $this->input->post('mobile_no');
                $voucher = $this->user_working->get_voucher_by_mobile_no($mobile_no);
                
                if($voucher){
                    // 替换成你实际要更新的voucher字段,比如paid/unpaid状态
                    $voucher_data = array(
                        'status' => $this->input->post('voucher_status'),
                        'updated_at' => date('Y-m-d H:i:s')
                    );
                    $voucher_result = $this->user_working->update_voucher_by_mobile($voucher_data, $mobile_no);
                    
                    $flash_msg = $voucher_result ? '用户及发票状态已成功更新!' : '用户更新成功,但发票状态更新失败!';
                } else {
                    // 如果没有对应voucher记录,可选择创建新记录(根据业务需求)
                    /*
                    $new_voucher = array(
                        'mobile_no' => $mobile_no,
                        // Invoice_no是自增字段,无需赋值,数据库自动生成
                        'status' => 'unpaid', // 默认状态
                        // 其他必填字段请补充
                    );
                    $this->db->insert('voucher', $new_voucher);
                    */
                    $flash_msg = '用户更新成功,但未找到对应发票记录!';
                }
                
                $this->session->set_flashdata('msg', $flash_msg);
                redirect(base_url('user/users'));
            }
        }
    } else{
        $data['user'] = $this->user_working->get_user_by_id($id);
        $data['user_groups'] = $this->user_working->get_user_groups();
        $data['view'] = 'user/users/user_edit';
        $this->load->view('layout', $data);
    }
}

//-----------------------------------------------------------------------
public function del($id = 0){
    $user = $this->user_working->get_user_by_id($id);
    if($user){
        // 注意:删除用户时需要同步处理voucher表(根据外键约束,要么级联删除,要么先删voucher)
        $this->db->delete('voucher', array('mobile_no' => $user['mobile_no']));
        $this->db->delete('ci_users', array('id' => $id));
        $this->session->set_flashdata('msg', '用户已成功删除!');
    } else {
        $this->session->set_flashdata('msg', '用户不存在!');
    }
    redirect(base_url('user/users'));
}

4. 额外排查建议

  • 查看具体SQL报错:打开CodeIgniter的日志功能(在application/config/config.php中设置$config['log_threshold'] = 2;),日志文件在application/logs目录下,里面会有详细的SQL执行错误信息,这是排查数据库问题最直接的方式。
  • 外键约束检查:voucher表的mobile_no是外键关联ci_users的mobile_no,如果用户编辑时修改了手机号,需要确保新手机号在ci_users中存在,否则会触发外键约束报错;或者限制用户不能修改手机号。
  • 自增字段处理:Invoice_no是自增字段,插入voucher记录时不要给该字段赋值,让数据库自动生成,否则会违反自增规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:00:45