Zend Framework 1.x 的 Zend_Db_Select 提供流暢的 join() 方法支援多表關聯查詢。本文展示內連接、左/右連接、多條件連接、欄位別名、條件過濾等實用模式。
$select = $db->select();
$select->from('table1', ['col1', 'col2']) // 主表與欄位
->join('table2', 'table1.id = table2.fk_id', ['col3', 'col4']) // 內連接
->joinLeft('table3', 'table1.id = table3.fk_id', ['col5']) // 左連接
->joinRight('table4', 'table1.id = table4.fk_id', ['col6']) // 右連接
->joinFull('table5', 'table1.id = table5.fk_id', ['col7']); // 全連接 (MySQL 不支援,模擬)
<?php
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Db');
Zend_Loader::loadClass('Zend_Db_Statement_Pdo');
$config = [
'host' => '127.0.0.1',
'username' => 'root',
'password' => '111',
'dbname' => 'test',
'profiler' => true
];
$db = Zend_Db::factory('PDO_Mysql', $config);
$db->query('SET NAMES utf8');
// 建構關聯查詢
$select = $db->select();
$select->from('sanguo', ['*']) // sanguo 表所有欄位
->join('dengji', 'sanguo.s_dengji = dengji.d_id', ['d_name as 等級名稱']) // 關聯 dengji 表,指定欄位別名
->order('s_dengji ASC'); // 排序
// 執行查詢
$results = $db->fetchAll($select);
// 輸出結果
echo "<table border='1' width='600' style='text-align:center'>";
foreach ($results as $row) {
echo "<tr>";
foreach ($row as $val) {
echo "<td>$val</td>";
}
echo "</tr>";
}
echo "</table>";
?>
| 方法 | SQL 類型 | 用途 | 備註 |
|---|---|---|---|
join($table, $cond, $cols) | INNER JOIN | 僅返回雙方都匹配的行 | 最常用 |
joinLeft($table, $cond, $cols) | LEFT JOIN | 返回左表所有行,右表無匹配則 NULL | 保留主表完整資料 |
joinRight($table, $cond, $cols) | RIGHT JOIN | 返回右表所有行,左表無匹配則 NULL | 較少用 |
joinFull($table, $cond, $cols) | FULL JOIN | 返回雙方所有行,無匹配填 NULL | MySQL 不支援,ZF 模擬為 UNION |
joinCross($table, $cols) | CROSS JOIN | 笛卡兒積,無 ON 條件 | 慎用 |
joinNatural($table, $cols) | NATURAL JOIN | 自動以同名欄位連接 | 隱含風險,不建議 |
$select->join('order_items',
'orders.id = order_items.order_id AND order_items.status = ?',
['item_name', 'price'],
'active'); // 關聯別名,避免欄位名衝突
$subQuery = $db->select()
->from('stats', ['user_id', 'total_amount' => 'SUM(amount)'])
->group('user_id');
$select = $db->select()
->from('users', ['id', 'username'])
->join(['s' => $subQuery], 'users.id = s.user_id', ['total_amount']);
// 陣列格式:['原欄位名 as 別名', '另一欄位']
->join('dengji', 'sanguo.s_dengji = dengji.d_id', ['d_name as 等級名稱'])
// 或使用關聯陣列 (ZF 1.10+)
->join('dengji', 'sanguo.s_dengji = dengji.d_id', ['等級名稱' => 'd_name'])
// 同表自連接或多次連接同表時必須別名
->join(['m' => 'members'], 'orders.member_id = m.id', ['m.name as 會員名'])
->join(['r' => 'members'], 'orders.referrer_id = r.id', ['r.name as 推薦人'])
id, created_at) 時,務必在第三參數明確指定需要的欄位並加別名,否則結果陣列會被覆蓋。join() 的第二參數只接受 ON 條件。額外過濾條件請用 where() 或 orWhere()。limitPage() 在 Join 查詢中同樣適用,但注意 COUNT(*) 統計總數時需使用相同的 Join 條件,否則總數不準。SELECT *,只取必要欄位;考慮分表、快取、唯讀副本。SELECT `sanguo`.*, `dengji`.`d_name` AS `等級名稱`
FROM `sanguo`
INNER JOIN `dengji` ON `sanguo`.`s_dengji` = `dengji`.`d_id`
ORDER BY `s_dengji` ASC
Zend_Db_Select 的 Join API 設計直觀,支援各種連接類型與進階場景。掌握欄位別名、關聯別名、子查詢連接等技巧,能輕鬆應對複雜關聯查詢需求。現代專案遷移至 Laminas Db 或 Doctrine DBAL 時,Join 語法高度相容,遷移成本極低。