首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Zend Framework Zend_Db Select Join 關聯查詢完整範例

     編輯:PHP 相關知識

Zend Framework 1.x 的 Zend_Db_Select 提供流暢的 join() 方法支援多表關聯查詢。本文展示內連接、左/右連接、多條件連接、欄位別名、條件過濾等實用模式。

基本 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>";
?>

Join 方法完整對照表

方法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返回雙方所有行,無匹配填 NULLMySQL 不支援,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) 時,務必在第三參數明確指定需要的欄位並加別名,否則結果陣列會被覆蓋。
  • WHERE 條件位置:join() 的第二參數只接受 ON 條件。額外過濾條件請用 where() 或 orWhere()。
  • 分頁與 Join:limitPage() 在 Join 查詢中同樣適用,但注意 COUNT(*) 統計總數時需使用相同的 Join 條件,否則總數不準。
  • 效能:大表 Join 確保 ON 欄位有索引;避免 SELECT *,只取必要欄位;考慮分表、快取、唯讀副本。

生成的 SQL 範例

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 語法高度相容,遷移成本極低。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved