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
相关产品推荐
相关产品推荐

