Zend Framework 1.x 的 Zend_Db 元件提供物件導向的 SQL 建構器 (Zend_Db_Select) 與分頁支援。本文展示完整的分頁查詢流程:從資料庫連線、總筆數統計、Select 物件建構、分頁邏輯到前端頁碼輸出。
<?php
// 取得當前頁碼
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
// 載入類別
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
];
// 建立資料庫連線 (PDO_Mysql)
$db = Zend_Db::factory('PDO_Mysql', $config);
$db->query('SET NAMES utf8');
// 1. 取得總筆數
$total = $db->fetchOne('SELECT COUNT(*) FROM gongsi');
// 2. 分頁參數
$perPage = 50;
$totalPages = ceil($total / $perPage);
// 3. 建構 Select 物件
$select = $db->select();
$select->from('sanguo', [
's_sheng as 省份',
'sum(s_gongzi) as 總工資',
'min(s_gongzi) as 最低工資',
'max(s_gongzi) as 最高工資',
'avg(s_gongzi) as 平均工資'
]);
// 可選條件
// $select->where('s_gongzi >= ?', 3000);
// $select->where("s_sheng = ?", '河北');
$select->group('s_sheng');
$select->having('最高工資 > ?', 10000);
$select->order('最高工資 DESC');
// 4. 套用分頁 (頁碼從 1 開始,內部自動計算 offset)
$select->limitPage($page, $perPage);
// 5. 執行查詢
$results = $db->fetchAll($select);
// 6. 輸出表格
echo "";
echo "省份 總工資 最低工資 最高工資 平均工資 ";
foreach ($results as $row) {
echo "";
foreach ($row as $val) {
echo "$val ";
}
echo " ";
}
// 7. 輸出分頁導航
echo "";
echo "首頁 ";
if ($page > 1) echo "上頁 ";
for ($i = 1; $i <= min(15, $totalPages); $i++) {
echo "$i ";
}
if ($page < $totalPages) echo "下頁 ";
echo "末頁";
echo "
";
?>
from()、where()、group()、having()、order()、limitPage()。where('col = ?', $val) 自動處理引號與轉義,防 SQL 注入。// 相當於
$select->limit($perPage, ($page - 1) * $perPage);
// 即 LIMIT offset, count
頁碼從 1 起算,內部自動換算 offset,開發者無需手動計算。
配置 'profiler' => true 後,可透過 $db->getProfiler() 取得查詢耗時、SQL 文本等資訊,利於優化。
1 ... 5 6 7 ... 100,避免過長導航列。http_build_query(array_merge($_GET, ['page' => $i]))。rel="prev/next"、canonical 標籤。GROUP BY 配合 LIMIT 可能導致結果不穩定,建議加上確定性 ORDER BY。LIMIT 100000, 50 需掃描前 10 萬行。百萬級資料建議用「游標分頁」(WHERE id > last_id)替代。COUNT(*) 可能很慢,可考慮快取總數、使用近似值或延遲載入。paginate()。Zend_Db_Select 的 limitPage() 讓分頁查詢變得直觀易維護。結合 Profiler 與參數綁定,能寫出安全、高效、可測試的資料存取層。理解其生成的 SQL 結構,有助於在必要時手寫優化查詢。