where() 核心簽名
$this->db->where($key, $value = null, $escape = true)
$key:欄位名、條件字串、或關聯陣列
$value:值 (若 $key 為字串條件則忽略)
$escape:是否轉義/加反引號,FALSE 時不處理,用於原生 SQL 片段
六大變體方法對照表
| 方法 | SQL 連接詞 | 用途 |
where() | AND | 標準條件 |
or_where() | OR | 或條件 |
where_in() | AND | IN 子查詢 |
or_where_in() | OR | OR IN |
where_not_in() | AND | NOT IN |
or_where_not_in() | OR | OR NOT IN |
詳細用法範例
1. 基礎鍵值對 (自動轉義)
$this->db->where('status', 1);
// WHERE `status` = 1
$this->db->where('name', 'John\'s');
// WHERE `name` = 'John\'s' (自動轉義單引號)
2. 自定義運算子 (第三參數 FALSE)
$this->db->where('created_at >', '2023-01-01', false);
// WHERE `created_at` > '2023-01-01'
$this->db->where('MATCH(title) AGAINST("keyword")', null, false);
// WHERE MATCH(title) AGAINST("keyword") (全文搜索)
3. 關聯陣列批量條件 (隱含 AND)
$this->db->where([
'status' => 1,
'type' => 'article',
'author_id' => 5,
]);
// WHERE `status` = 1 AND `type` = 'article' AND `author_id` = 5
4. or_where() 串聯 OR 條件
$this->db->where('status', 1);
$this->db->or_where('role', 'admin');
// WHERE `status` = 1 OR `role` = 'admin'
// 陣列版
$this->db->or_where(['role' => 'admin', 'role' => 'editor']);
// WHERE `role` = 'admin' OR `role` = 'editor'
5. where_in() / or_where_in()
$ids = [1, 2, 3, 5, 8];
$this->db->where_in('id', $ids);
// WHERE `id` IN (1, 2, 3, 5, 8)
$this->db->or_where_in('category', ['news', 'blog', 'tech']);
// WHERE `category` IN ('news', 'blog', 'tech') (以 OR 連接上一條件)
6. where_not_in() / or_where_not_in()
$banned = [99, 100, 999];
$this->db->where_not_in('user_id', $banned);
// WHERE `user_id` NOT IN (99, 100, 999)
$this->db->or_where_not_in('status', [-1, 0]);
// WHERE `status` NOT IN (-1, 0) (OR 連接)
複雜條件組合模式
巢狀 AND/OR 群組 (CI 3 不原生支援,需用 where 字串)
// (status=1 AND type='a') OR (status=2 AND type='b')
$this->db->where("(status = 1 AND type = 'a') OR (status = 2 AND type = 'b')", null, false);
子查詢條件
$subQuery = $this->db->select('user_id')->where('role', 'admin')->get_compiled_select('users');
$this->db->where("id IN ($subQuery)", null, false);
動態條件建構器模式
function buildFilters($filters) {
foreach ($filters as $field => $condition) {
if (is_array($condition)) {
// ['in' => [1,2,3]] 或 ['between' => [1,10]] 或 ['!=' => 0]
foreach ($condition as $op => $val) {
switch ($op) {
case 'in': $this->db->where_in($field, $val); break;
case 'not_in': $this->db->where_not_in($field, $val); break;
case 'between': $this->db->where("$field BETWEEN {$val[0]} AND {$val[1]}", null, false); break;
default: $this->db->where("$field $op ?", $val); // !=, >, <, >=, <=, LIKE
}
}
} else {
$this->db->where($field, $condition);
}
}
}
// 使用
$filters = [
'status' => 1,
'category' => ['in' => ['news', 'tech']],
'views' => ['between' => [100, 10000]],
'deleted_at' => ['!=' => null],
];
buildFilters($filters);
效能與安全提醒
| 項目 | 建議 |
| 防注入 | 優先用鍵值對/陣列形式,自動參數化;僅在複雜 SQL 片段用 escape=false 並自行驗證 |
| 索引利用 | 高選擇性欄位優先放 where,避免導致全表掃描的條件在前 |
| IN 列表過長 | where_in 超過 1000 個值會報錯,改用臨時表或 JOIN |
| NULL 比較 | 用 where('col', null) 產生 IS NULL,where('col !=', null) 產生 IS NOT NULL |
除錯技巧
// 獲取編譯後 SQL (不執行)
$sql = $this->db->get_compiled_select('articles');
echo $sql;
// SELECT * FROM `articles` WHERE `status` = 1 AND `category` IN ('news', 'tech')
// 獲取最後執行 SQL
$this->db->last_query();
總結
CI where() 族群提供靈活的條件建構能力:鍵值對最安全、字串條件最強大、IN/NOT IN 專用方法最優雅。掌握六大變體與動態建構模式,即可應對 99% 的查詢場景。複雜巢狀邏輯建議用原生 SQL 片段 (escape=false) 或子查詢,並善用 get_compiled_select() 除錯驗證生成 SQL。