Zend_Db 底層依賴 PDO,必須在 php.ini 啟用:
extension=php_pdo.dll
extension=php_pdo_mysql.dll
extension_dir = "C:/php5/ext" ; 指向 DLL 實際目錄
重啟 Apache/IIS 後,phpinfo() 應顯示 PDO drivers: mysql。
ZF1 採用 Front Controller 模式,index.php 為唯一入口,建立資料庫連線並存入 Zend_Registry 供全域存取。
<?php
// index.php
require_once 'Zend/Loader/Autoloader.php';
Zend_Loader_Autoloader::getInstance()->setFallbackAutoloader(true);
// 資料庫連線參數
$params = [
'host' => '127.0.0.1',
'username' => 'root',
'password' => '123456',
'dbname' => 'happycms',
'charset' => 'utf8', // 重要:設定連線字符集
'driver_options' => [
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
]
];
// 工廠方法建立適配器
$db = Zend_Db::factory('Pdo_Mysql', $params);
// 存入註冊表,鍵名 'db'
Zend_Registry::set('db', $db);
// 啟動前端控制器
$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory('./application/controllers');
$front->dispatch();
?>
<?php
// application/models/Article.php
class App_Article {
private Zend_Db_Adapter_Abstract $db;
public function __construct() {
$this->db = Zend_Registry::get('db');
}
public function listAll(): array {
// 直接查詢並返回陣列
return $this->db->fetchAll('SELECT * FROM article');
}
public function listByCategory(int $categoryId): array {
// 參數綁定防注入
return $this->db->fetchAll(
'SELECT * FROM article WHERE category_id = ? ORDER BY addtime DESC',
[$categoryId]
);
}
public function getById(int $id): ?array {
return $this->db->fetchRow('SELECT * FROM article WHERE articleid = ?', [$id]);
}
}
?>
<?php
// application/controllers/ArticleController.php
class ArticleController extends Zend_Controller_Action {
private App_Article $article;
private Zend_View_Interface $view;
public function init() {
$this->article = new App_Article();
$this->view = Zend_Registry::get('view'); // 假設 bootstrap 已註冊 view
}
public function listAllAction() {
$articles = $this->article->listAll();
$this->view->articles = $articles;
$this->view->title = '文章列表';
// 渲染 scripts/article/listAll.phtml
}
public function viewAction() {
$id = (int)$this->_getParam('id', 0);
$article = $this->article->getById($id);
if (!$article) {
$this->_redirect('/article/listAll');
return;
}
$this->view->article = $article;
}
}
?>
<!-- application/views/scripts/article/listAll.phtml -->
<h1>= $this->escape($this->title) ?></h1>
<table class="table">
<thead>
<tr><th>ID</th><th>標題</th><th>分類</th><th>作者</th><th>發布時間</th></tr>
</thead>
<tbody>
articles as $article): ?>
<tr>
<td>= $article['articleid'] ?></td>
<td><a href="/article/view/id/= $article['articleid'] ?>">= $this->escape($article['articletitle']) ?></a></td>
<td>= $article['categoryid'] ?></td>
<td>= $this->escape($article['authorname']) ?></td>
<td>= $article['addtime'] ?></td>
</tr>
</tbody>
</table>
| 操作 | 方法 | 範例 |
|---|---|---|
| 查詢單行 | fetchRow() | $db->fetchRow('SELECT * FROM t WHERE id=?', [$id]) |
| 查詢多行 | fetchAll() | $db->fetchAll('SELECT * FROM t WHERE status=?', ['active']) |
| 查詢單值 | fetchOne() | $db->fetchOne('SELECT COUNT(*) FROM t') |
| 查詢單欄 | fetchCol() | $db->fetchCol('SELECT id FROM t') |
| 插入資料 | insert() | $db->insert('t', ['col1'=>'val1', 'col2'=>'val2']) |
| 更新資料 | update() | $db->update('t', ['col1'=>'new'], 'id=5') |
| 刪除資料 | delete() | $db->delete('t', 'id=5') |
| 預處理執行 | query() + 參數陣列 | $db->query('SELECT * FROM t WHERE a=? AND b=?', [$a, $b]) |
| 事務控制 | beginTransaction()/commit()/rollBack() | $db->beginTransaction(); ... $db->commit(); |
| 引用識別符 | quoteIdentifier() | $db->quoteIdentifier('order') → `order` |
確認 Zend_Db::factory() 第一參數為 'Pdo_Mysql'(大小寫敏感),且 php_pdo_mysql.dll 已載入。
連線參數加入 'charset' => 'utf8' 及 PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8';資料表/欄位字符集設為 utf8mb4。
嚴禁字串拼接 SQL。永遠使用 ? 佔位符或命名參數 :name,配合 fetchAll()、query()、insert() 等方法自動綁定。
$db->getProfiler()->setEnabled(true);
// 執行查詢後
foreach ($db->getProfiler()->getQueryProfiles() as $profile) {
echo $profile->getQuery() . "\n"; // 顯示實際執行 SQL 含參數
}
Zend_Db 以 適配器模式 統一資料庫操作,配合 Zend_Registry 實現連線共享,提供豐富的查詢方法與防注入機制。掌握「入口建立連線 → 註冊表存取 → 模型封裝查詢 → 控制器協調 → 視圖渲染」完整鏈路,即可在 ZF1 專案中高效、安全地操作 MySQL。