CodeIgniter 3.1.5中or_where_in与其他where条件的正确用法咨询
解决CodeIgniter 3.1.5中
or_where_in与其他条件配合的逻辑错误问题 我来帮你排查这个问题,核心原因是逻辑运算符的优先级导致的,咱们一步步说清楚:
问题根源
当你直接使用or_where_in时,它会和后面的日期where条件形成OR逻辑关系,最终生成的SQL大概是这样的:
SELECT * FROM bills WHERE type = ? AND user_id = ? OR user_id IN (?, ?, ...) AND DATE(created_at) BETWEEN 'xxx' AND 'xxx'
因为SQL中AND的优先级高于OR,这就会导致只要满足user_id IN (...)的记录,不管日期是否在范围内都会被返回——这就是你看到“返回未选中日期结果”的原因。而改用where_in时,可能是因为没有同时满足user_id = $user_id和user_id IN $get_all_user_ids的记录,所以无数据返回。
正确的写法:用分组包裹OR条件
CodeIgniter提供了group_start()和group_end()方法来帮你把一组条件用括号包裹,确保逻辑符合预期。修改后的代码如下:
public function get_date_wise_sales_info($start_date, $end_date,$type=NULL,$user_id=NULL,$get_all_user_ids=NULL) { if(!empty($type)) { $this->db->where('type',$type); } // 把用户ID的相关条件分组,确保OR只在这组内生效 if(!empty($user_id) || !empty($get_all_user_ids)) { $this->db->group_start(); // 生成左括号 if(!empty($user_id)) { $this->db->where('user_id', $user_id); } if(!empty($get_all_user_ids)) { $this->db->or_where_in('user_id',$get_all_user_ids); } $this->db->group_end(); // 生成右括号 } // 建议用参数绑定避免SQL注入风险 $this->db->where("DATE(bills.created_at) BETWEEN ? AND ?", array($start_date, $end_date)); $this->db->order_by('bills.id','desc'); $query = $this->db->get('bills'); return $query->result(); }
为什么这样有效?
修改后生成的SQL会变成:
SELECT * FROM bills WHERE type = ? AND (user_id = ? OR user_id IN (?, ?, ...)) AND DATE(created_at) BETWEEN 'xxx' AND 'xxx'
括号把用户ID的两个条件包裹成一个整体,和其他条件都是AND关系,这样就保证了:
- 必须满足日期范围
- 同时满足type条件(如果有)
- 同时满足“指定user_id”或者“user_id在数组中”的其中一个条件
另外补充个小提示:直接把日期变量拼到SQL里存在SQL注入风险,我上面改成了参数绑定的写法,这是更安全的做法哦。
内容的提问来源于stack exchange,提问作者user_777
相关产品推荐
相关产品推荐

