<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" 
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>網站製作學習誌-Zend Framework</title>
<link>http://blog.roodo.com/jaceju/archives/cat_446359.html</link>
<description>
首頁
讀者留言版
管理介面












_uacct = &quot;UA-450710-1&quot;;
urchinTracker();
</description>
<language>zh-tw</language>
<generator>Roodo Blog System</generator>
<copyright>All Rights Reserved</copyright>
<atom:link href="http://blog.roodo.com/jaceju/archives/cat_446359.xml" rel="self" type="application/rss+xml" />
<item>
	<title>[PHP-ZF] 解決 ZF 在 Proxy 模式下無法正確解析 Controller Name 的問題</title>
	<description><![CDATA[
	說明
因為要和客戶的內部網路連線，便透過 PieTTY 的 SSH Tunnels 模式來做 Proxy 。 但是這個方式卻讓 Zend Framework 出現了以下的錯誤訊息：
An error occurred with this request: Invalid controller specified (http:).
解決方式是修改 Zend Framework 的 Zend_Controller_Request_Http 這個類別。
先開啟 Zend/Controller/Request/Http.php ，並找到：
$requestUri = $_SERVER['REQUEST_URI'];
改為：
$requestUri = preg_replace(
    '/^https?:\/\/' . $_SERVER['HTTP_HOST'] . '/i',
    '',
    $_SERVER['REQUEST_URI']
);
這樣就能避掉 Proxy 所帶來的問題了。
註 1 ：這個方法的風險在於會修改原生的 ZF 程式碼，如果會用到 Subversion 來管理程式碼的話，要特別注意未來更新版本時可能會發生衝突的問題。
註 2 ：未來版本應該會修正這個問題。
參考
 ZF MVC is not compatible with apache + http protocol proxy requests

	]]>
	</description>
	<content:encoded><![CDATA[
	<h2>說明</h2>
<p>因為要和客戶的內部網路連線，便透過 <a href="http://cha.homeip.net/blog/archives/2006/01/putty_ssh_tunne.html">PieTTY 的 SSH Tunnels 模式</a>來做 Proxy 。 但是這個方式卻讓 Zend Framework 出現了以下的錯誤訊息：</p>
<pre><code>An error occurred with this request: Invalid controller specified (http:).</code></pre>
<p>解決方式是修改 Zend Framework 的 Zend_Controller_Request_Http 這個類別。</p>
<p>先開啟 Zend/Controller/Request/Http.php ，並找到：</p>
<pre><code>$requestUri = $_SERVER['REQUEST_URI'];</code></pre>
<p>改為：</p>
<pre><code>$requestUri = preg_replace(
    '/^https?:\/\/' . $_SERVER['HTTP_HOST'] . '/i',
    '',
    $_SERVER['REQUEST_URI']
);</code></pre>
<p>這樣就能避掉 Proxy 所帶來的問題了。</p>
<p class="note">註 1 ：這個方法的風險在於會修改原生的 ZF 程式碼，如果會用到 Subversion 來管理程式碼的話，要特別注意未來更新版本時可能會發生衝突的問題。</p>
<p class="note">註 2 ：未來版本應該會修正這個問題。</p>
<h2>參考</h2>
<p> <a href="http://framework.zend.com/issues/browse/ZF-3161?page=com.atlassian.jira.plugin.system.issuetabpanels:changehistory-tabpanel">ZF MVC is not compatible with apache + http protocol proxy requests</a></p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/6217407.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/6217407.html</guid>
	<category>Zend Framework</category>
	<pubDate>Mon, 23 Jun 2008 11:09:41 +0800</pubDate>
</item>
<item>
	<title>[PHP-ZF] 如何學習 Zend Framework</title>
	<description><![CDATA[
	今天又被問到怎麼開始學 Zend Framework ，我是覺得要上手並不難，但是基礎一定要有。
那麼哪些東西算是基礎呢？當然 HTML 、 JavaScript (Ajax) 或 CSS 等必備技能就不必多說了；以下我介紹幾個我個人認為滿重要的部份以及學習的次序：

物件導向

學習 Zend Framework 時，絕大部份時間你一定會接觸到物件導向，因此物件導向的基本觀念是一定要有的；否則你在運用 ZF 的各種套件時，一定會陷入困惑的泥沼中。 
至於物件導向的三大要素：封裝、繼承和多型，詳細的說明在書本或網路有很多，我就不在這裡野人獻曝囉。這裡推薦：「深入淺出 Java 程式設計」，其中幾章的物件導向概念值得一讀。

設計模式

有了物件導向的觀念後，我強烈建議去瞭解設計模式，因為在 Zend Framework 的套件在設計上用到了許多設計模式。而且我個人也認為適當運用設計模式，能讓我們的程式更強固且具有彈性。
不過我很難用明確的字眼去表達設計模式是什麼東西，那遠遠超出我的能力範圍。因此我推薦這本：「深入淺出設計模式」，它簡單易懂的範例與說明，看完後保證你在物件導向上的功力能增進一甲子。

MVC 概念

MVC 觀念常常是傳統 PHP 開發者所不瞭解的，因為如果能快速把工作完成，誰會想去搞一個看起來那麼複雜的玩意兒？但是 MVC 在運用得當的情況下，卻能讓程式的意圖更加清晰，而且也更容易維護。
事實上 MVC 也是設計模式的一種，而上面那本書裡裡也有提到，建議大家參考看看。不過 Zend Framework 的 WebMVC 在實作上的概念上有稍有不同，我個人自薦這篇：「透視 WebMVC 」；該文會告訴你如何將舊有的 PHP 專案轉換成 MVC 架構。  

PHP5

由於 Zend Framework 在開發上採用了 PHP5 的特性，所以 PHP5 也變成學習 Zend Framework 時最重要的基礎之一。而 PHP5 在物件導向也著墨甚多，在語法上也參考 Java 的許多特點，學過 Java 的朋友一定倍感親切。
參考資料方面我個人推薦官方手冊的 PHP5 的 Classes and Objects 一節，另外還有 Standard PHP Library (SPL) Functions 。 

一定的開發經驗

Zend Framework 已經幫我們把很多東西都包裝好了，因此我們很多時候都可以不用重造輪子。但是它只是個工具，而且也不是萬能的，因此有些東西還是需要靠你自己來；所以對於 Web 開發你就必須要有一定程度的瞭解，至少你得曾經獨力完成一個以上的專案。 

入門教學

假設以上你都有了一定的基礎，那麼你還需要臨門的一腳。一篇好的入門文章絕對是你學習 Zend Framework 必要的利器之一，因為它能快速帶你進入 Zend Framework 的世界裡。 
這裡就不能不提 Rob Allen 寫的文章了，這篇「 Getting Started with Zend Framework 」是學習 Zend Framework 的你一定要載回來仔細研究的好文！不過官方也提供了一篇 Quick Start ，你可以將它和 Rob Allen 的文章交互參考看看 (我個人覺得 Rob 的比較完整) 。 

參考手冊與源代碼

如果你已經入門了，那可別鬆懈。因為 Zend Framework 裡面有許多好用的工具，只是看你懂不懂得去運用而已；所以官方的參考手冊和 API 說明是一定要去看的。而源代碼更是重要，因為當官方手冊的範例或 API 說明明顯不足時，你可以從源代碼裡挖出一些不為人知的秘技，更可以學到許多高深的技巧！ 


當然以上的基礎不是絕對的，這僅僅是我個人的一些建議而已。希望這篇簡單的說明能幫助大家順利學習 Zend Framework ，也期盼大家能一起分享更多的學習心得。 

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>今天又被問到怎麼開始學 Zend Framework ，我是覺得要上手並不難，但是基礎一定要有。</p>
<p>那麼哪些東西算是基礎呢？當然 HTML 、 JavaScript (Ajax) 或 CSS 等必備技能就不必多說了；以下我介紹幾個我個人認為滿重要的部份以及學習的次序：</p>
<dl>
<dt>物件導向</dt>
<dd>
<p>學習 Zend Framework 時，絕大部份時間你一定會接觸到物件導向，因此物件導向的基本觀念是一定要有的；否則你在運用 ZF 的各種套件時，一定會陷入困惑的泥沼中。 </p>
<p>至於物件導向的三大要素：<strong>封裝</strong>、<strong>繼承</strong>和<strong>多型</strong>，詳細的說明在書本或網路有很多，我就不在這裡野人獻曝囉。這裡推薦：「<a href="http://tlsj.tenlong.com.tw/WebModule/BookSearch/bookSearchViewAction.do?isbn=9867794605&amp;sid=28153" target="_blank">深入淺出 Java 程式設計</a>」，其中幾章的物件導向概念值得一讀。</p>
</dd>
<dt>設計模式</dt>
<dd>
<p>有了物件導向的觀念後，我強烈建議去瞭解<strong>設計模式</strong>，因為在 Zend Framework 的套件在設計上用到了許多設計模式。而且我個人也認為適當運用設計模式，能讓我們的程式更強固且具有彈性。</p>
<p>不過我很難用明確的字眼去表達設計模式是什麼東西，那遠遠超出我的能力範圍。因此我推薦這本：「<a href="http://tlsj.tenlong.com.tw/WebModule/BookSearch/bookSearchViewAction.do?isbn=9867794524&amp;sid=32306" target="_blank">深入淺出設計模式</a>」，它簡單易懂的範例與說明，看完後保證你在物件導向上的功力能增進一甲子。</p>
</dd>
<dt>MVC 概念</dt>
<dd>
<p>MVC 觀念常常是傳統 PHP 開發者所不瞭解的，因為如果能快速把工作完成，誰會想去搞一個看起來那麼複雜的玩意兒？但是 MVC 在運用得當的情況下，卻能讓程式的意圖更加清晰，而且也更容易維護。</p>
<p>事實上 MVC 也是設計模式的一種，而上面那本書裡裡也有提到，建議大家參考看看。不過 Zend Framework 的 WebMVC 在實作上的概念上有稍有不同，我個人自薦這篇：「<a href="http://www.jaceju.net/resources/webmvc/" target="_blank">透視 WebMVC</a> 」；該文會告訴你如何將舊有的 PHP 專案轉換成 MVC 架構。  </p>
</dd>
<dt>PHP5</dt>
<dd>
<p>由於 Zend Framework 在開發上採用了 PHP5 的特性，所以 PHP5 也變成學習 Zend Framework 時最重要的基礎之一。而 PHP5 在物件導向也著墨甚多，在語法上也參考 Java 的許多特點，學過 Java 的朋友一定倍感親切。</p>
<p>參考資料方面我個人推薦官方手冊的 PHP5 的 <a href="http://www.php.net/manual/en/language.oop5.php" target="_blank">Classes and Objects</a> 一節，另外還有 <a href="http://www.php.net/manual/en/ref.spl.php" target="_blank">Standard PHP Library (SPL) Functions</a> 。 </p>
</dd>
<dt>一定的開發經驗</dt>
<dd>
<p>Zend Framework 已經幫我們把很多東西都包裝好了，因此我們很多時候都可以不用重造輪子。但是它只是個工具，而且也不是萬能的，因此有些東西還是需要靠你自己來；所以對於 Web 開發你就必須要有一定程度的瞭解，至少你得曾經獨力完成一個以上的專案。 </p>
</dd>
<dt>入門教學</dt>
<dd>
<p>假設以上你都有了一定的基礎，那麼你還需要臨門的一腳。一篇好的入門文章絕對是你學習 Zend Framework 必要的利器之一，因為它能快速帶你進入 Zend Framework 的世界裡。 </p>
<p>這裡就不能不提 Rob Allen 寫的文章了，這篇「 <a href="http://akrabat.com/zend-framework-tutorial/" target="_blank">Getting Started with Zend Framework</a> 」是學習 Zend Framework 的你一定要載回來仔細研究的好文！不過官方也提供了一篇 <a href="http://framework.zend.com/wiki/display/ZFDEV/Official+ZF+QuickStart" target="_blank">Quick Start</a> ，你可以將它和 Rob Allen 的文章交互參考看看 (我個人覺得 Rob 的比較完整) 。 </p>
</dd>
<dt>參考手冊與源代碼</dt>
<dd>
<p>如果你已經入門了，那可別鬆懈。因為 Zend Framework 裡面有許多好用的工具，只是看你懂不懂得去運用而已；所以官方的<a href="http://framework.zend.com/manual/en/" target="_blank">參考手冊</a>和 <a href="http://framework.zend.com/apidoc/core/" target="_blank">API 說明</a>是一定要去看的。而源代碼更是重要，因為當官方手冊的範例或 API 說明明顯不足時，你可以從源代碼裡挖出一些不為人知的秘技，更可以學到許多高深的技巧！ </p>
</dd>
</dl>
<p>當然以上的基礎不是絕對的，這僅僅是我個人的一些建議而已。希望這篇簡單的說明能幫助大家順利學習 Zend Framework ，也期盼大家能一起分享更多的學習心得。 </p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/5781987.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/5781987.html</guid>
	<category>Zend Framework</category>
	<pubDate>Mon, 31 Mar 2008 16:40:47 +0800</pubDate>
</item>
<item>
	<title>Zend Framework 1.5 正式推出</title>
	<description><![CDATA[
	Zend Framework 1.5 正式推出了！
首先官方網站大改版！變得更漂亮了！而且也提供了官方版的快速入門，讓剛接觸的朋友也能很容易瞭解 ZF 1.5 的能耐。
主要更新特色如下：  


Forms - 提供類似 PEAR 的 HTML_QuickForm 。


Layout - 提供類似 ASP.Net 的 Master Page 模式。


LDAP/OpenID  authentication - 讓應用程式可以整合 LDAP 及 OpenID 的身份驗證。


Lucene search engine - 加強了搜尋語法。


Extended Ajax support - 支援動態的 Ajax 內容切換。


UTF-8 character sets in Adobe PDF creation - PDF 也能支援 UTF-8 字集。


Google GData web services - 加強了 GData 的操作。


Table Select - 能夠使用 Select 來操作 Table 了。 


然而之前說 1.5 可能會將 Command Line Build 放進來，但是很可惜的是時程沒趕上。不過上面這些 ZF 1.5 的新特色，很值得有用 ZF 開發的朋友參考看看喔。
其他詳細消息請參考： Zend Technologies Releases Zend Framework 1.5
註：剛剛看到 Rob 更新了他的教學： Updated Tutorial for Zend Framework 1.5  。

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>Zend Framework 1.5 正式推出了！</p>
<p>首先<a href="http://framework.zend.com/">官方網站</a>大改版！變得更漂亮了！而且也提供了官方版的<a href="http://framework.zend.com/wiki/display/ZFDEV/Official+ZF+QuickStart">快速入門</a>，讓剛接觸的朋友也能很容易瞭解 ZF 1.5 的能耐。</p>
<p>主要更新特色如下：  </p>
<ul>
<li>
<p>Forms - 提供類似 PEAR 的 HTML_QuickForm 。</p>
</li>
<li>
<p>Layout - 提供類似 ASP.Net 的 Master Page 模式。</p>
</li>
<li>
<p>LDAP/OpenID  authentication - 讓應用程式可以整合 LDAP 及 OpenID 的身份驗證。</p>
</li>
<li>
<p>Lucene search engine - 加強了搜尋語法。</p>
</li>
<li>
<p>Extended Ajax support - 支援動態的 Ajax 內容切換。</p>
</li>
<li>
<p>UTF-8 character sets in Adobe PDF creation - PDF 也能支援 UTF-8 字集。</p>
</li>
<li>
<p>Google GData web services - 加強了 GData 的操作。</p>
</li>
<li>
<p>Table Select - 能夠使用 Select 來操作 Table 了。 </p>
</li>
</ul>
<p>然而之前說 1.5 可能會將 Command Line Build 放進來，但是很可惜的是時程沒趕上。不過上面這些 ZF 1.5 的新特色，很值得有用 ZF 開發的朋友參考看看喔。</p>
<p>其他詳細消息請參考： <a href="http://devzone.zend.com/article/3270-Zend-Technologies-Releases-Zend-Framework-1.5">Zend Technologies Releases Zend Framework 1.5</a></p>
<p class="note">註：剛剛看到 Rob 更新了他的教學： <a href="http://akrabat.com/2008/03/17/updated-tutorial-for-zend-framework-15/">Updated Tutorial for Zend Framework 1.5</a>  。</p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/5714019.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/5714019.html</guid>
	<category>Zend Framework</category>
	<pubDate>Mon, 17 Mar 2008 22:44:31 +0800</pubDate>
</item>
<item>
	<title>[PHP-ZF] 目錄結構的安排</title>
	<description><![CDATA[
	Zend Framework 目錄結構的安排 (Directory Layout) 也是一個很讓初學者困擾的問題，而且不論是官方或是社群都推薦了很多方法，更讓剛接觸 Zend Framework 的朋友難以適從。
本文將探討 Zend Framework 目錄結構的特點以及幾個常見的目錄結構，讓各位開發者能夠對它們有所認知。
為什麼要有目錄結構
目錄結構主要目的如下：


將程式及相關文件分門別類，以便於管理。


便於設定相關存取權限。


讓開發者很快能找到要修改的檔案。


因此選定一個好的目錄結構，將會為你的專案開發帶來高效率且易維護等好處。
專案目錄要放在哪裡
有些目錄結構需要有修改 Apache httpd.conf 的權限，有些則不需要；也因此專案目錄的存放位置也變得很重要，因為這會牽扯到安全性的問題。
一般來說，需要修改 httpd.conf 權限的目錄結構類型，我們可以放在檔案系統的任何地方，並確定它能讓 Apache 正確存取與執行。而不需要修改 httpd.conf 的類型，通常是為了因應專案的可攜性或是開發者缺少系統管理權；這時專案目錄就要放在 Apache 預設提供可以存取的位置，例如 /home/username/htdocs 。 
常見的目錄結構
以下我們來看看幾個常見的目錄結構。
類型一：官方手冊的版本
官方手冊的「 7.1. Zend_Controller Quick Start 」一節裡提供了一個參考用的 Directory Layout ，我稍微做了一些修改，如下：
application/
    controllers/
        IndexController.php
        ErrorController.php
    models/
    views/
        scripts/
            index/
                index.phtml
            error/
                error.phtml
        helpers/
        filters/
library/
    Zend/
    (other libraries)/
html/
    scripts/
    images/
    styles/
    .htaccess (導向 index.php)
    index.php
說明
這是一個需要修改 httpd.conf 的目錄結構，也僅適用於單一功能的應用程式 (也就是單一模組) 。在安裝時我們必須修改 httpd.conf ，將專案的 Document Root 指向 html 這個目錄。 html 目錄除了做為 Document Root 外，其目地就是存放可公開的檔案，像是圖片、 JavaScript 或樣式表等等。而 application 目錄即為預設的模組，存放著 MVC 等三種類型的檔案 (即 controllers 、 models 及 views 等三個目錄) 。至於 library 目錄就比較隨意，我們只要確定它的執行權限，並且讓 PHP 能夠找到裡面所需要的類別即可。 
在預設模組中， controllers 目錄裡的 IndexController.php 與 ErrorController.php 都是一定要的，另外 views/scripts/index/index.phtml 和 views/scripts/error/error.phtml 也是如此；而原因可以參考 Front Controller 的基本應用技一文，這裡不再詳述。
這裡要特別說明 application/views 這個目錄，其中還區分成 scripts 、 helpers 及 filters 三個目錄。 scripts 主要放的就是 templates ，底下可以用小寫的 controller name 做為資料夾名稱以做為區別；而 helpers 和 filters 其實在實際應用上比較少用，所以通常我會把它們從結構中拿掉。
註：為了節省篇幅，在呈現目錄結構時，預設模組的相關必要檔案我會略掉，但實際應用時請記得加回去。 
另外 .htaccess (導向 index.php) 的實際內容如下：
RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
php_flag magic_quotes_gpc off
php_flag register_globals off 
在 .htaccess 的第一行中，由於 Zend Framework 支援自訂網址的功能，所以我們啟用了 RewriteEngine ，也就是設定為 on 。接著第二行我們加入一個 RewriteRule ，讓 index.php 處理所有非公開資源的 request 。
註：不過 Zend Framework 也支援沒有 mod_rewrite 的環境，我們只要在 Front Controller 中將 baseUrl 設定好就沒問題了，這點有機會再探討。
剩下兩行是 PHP 的設定，這邊就不再加以說明。
這種目錄結構最大的特色是將 index.php 放在 html 目錄下， 這樣的好處在於能提高對 application 目錄的安全掌控度，因為 application 目錄並不會直接曝露給外部的瀏覽者。但是這樣的結構也有一個很大的缺點，那就是可攜性很差！換句話說如果在測試環境所使用的網址是 http://localhost/myproject/ ，而正式上線的環境卻是 http://www.myproject.com/ ，那麼就要修改 httpd.conf 讓 html 目錄對應到正確的網址，這樣才有辦法讓程式正確執行。 
類型二： Rob Allen 的版本
在 Rob 的 Getting Started with the Zend Framework 一文中，他採用了和官方不同的目錄結構：
application/
    .htaccess (deny from all)
    controllers/
    models/
    views/
        filters/
        helpers/
        scripts/
library/
    Zend/
    (other libraries)/
    .htaccess (deny from all)
public/
    .htaccess (RewriteEngine off)
    images/
    scripts/
    styles/
.htaccess (導向 index.php)
index.php
說明
這種目錄結構也是屬於單一功能 (模組) 的類型，它的特色是不必在 httpd.conf 中指定 Document Root 。這種目錄結構將 application 、 library 、 public (即第一種版本的 html) 以及 index.php 放在同一層的專案根目錄下，再利用 .htaccess 去控制每個目錄結構的存取權。 
.htaccess (導向 index.php) 內容和官方版相同，請參考上面的說明。比較特別的是 application/.htacess 的內容為 deny from all ，這是要避免用戶直接從網址瀏覽 application 內的檔案；而 public/.htaccess 的內容則是 RewriteEngine off ，亦即關閉原本 .htaccess (導向 index.php) 對此目錄的影響，讓用戶可以直接瀏覽 public 內的檔案 (就是圖片、 JavaScript 及樣式表等等) 。 
index.php 則是從 public 目錄中往外移至專案根目錄，這樣就可以讓用戶直接存取 (因為一般我們會在 Apache 設定 index.php 為預設執行頁) 。
這種目錄結構剛好和官方版本相反，它非常俱有可攜性，也是一般開發 Zend Framework 專案常用的目錄結構型態。不過它也有很大的缺點，那就是當 mod_rewrite 被關閉或是 .htaccess 不被解析時，這種目錄會將 application 及 library 兩個目錄曝露出來，在安全性上就大打折扣；不過通常這樣的 httpd.conf 設定比較少見，也因此一般開發 Zend Framework 專案時，大多都會採用這種目錄結構。 
類型三： Gavin Vess 的 Conventional Modular 版本
前面兩種版本都是單一功能 (模組) ，不過如果專案需要前後台或多種功能時，通常就會使用模組機制。Zend Framework 支援了模組機制，因此在目錄結構上也需要做一些改變。
有一篇 Gavin Vess 所寫的 Choosing Your Application's Directory Layout 也討論到了有關 Zend Framework 在模組上的目錄結構安排。文章中有個 Conventional Modular 版本，我也做稍做了修改，如下： 
application/
    config/ (非必要)
    default/
        config/ (非必要)
        controllers/
        models/
        views/
    (module 1)/
        controllers/
        models/
        views/
    (module 2)/
        controllers/
        models/
        views/
htdocs/
    images/
    scripts/
    styles/
    .htaccess (導向 index.php)
    index.php
library/
    Zend/
    (other libraries)/
tmp/
    sessions/
    cache/
    view_compiles/
說明
很明顯地，這個版本是從官方版本演化而來的；它的主要特色是將原來 application 中的 MVC 三個目錄拿掉了，取而代之的是 default 、 module1 、 module2 等 MVC 模組。 
前面兩個版本都是以 application 為預設模組，因此我們不必在程式裡特別設定。但是在多模組的狀況下，我們需要指定 application 下的某個模組為預設模組；這部份的程式碼可以參考我在 「Front Controller 的基本應用技」一文中所提到的「進階的 Front Controller 用法」。 
其他的目錄也都能望名生義，這裡不再解說。
類型四：我的版本
最後介紹我自己所採用的版本。基本上它可以算是模組化的 Rob 版本，只是我為了專案開發需求，又再加入一些特別的目錄結構。 
app/
    .htaccess (deny from all)
    base/
    cron/
    etc/
    lib/
    tmp/
    mod/
        default/
            caches/
            controllers/
            models/
            views/
        (module 1)/
            caches/
            controllers/
            models/
            views/
        (module 2)/
            caches/
            controllers/
            models/
            views/
pub/
    .htaccess (RewriteEngine off)
    img/
    js/
    css/
.htaccess (導向 index.php)
index.php
說明
首先我將 application 及 public 的名稱分別縮短為 app 及 pub ，其它目錄名稱也改為較短的名稱。而所有的 .htaccess 則和 Rob 版的相同，因此也會有同樣的限制。 
另外我把放置 Zend Framwork 及其他 library 所在的 lib 目錄移入 app 目錄中以方便管理，  Gavin Vess 的 config 我也改成了 etc ，這點算是仿照 Gavin Vess 的 Classical (Unix/Linux-like) 版本。
其他幾個特點如下：


加入了 base 目錄，這是用來存放專案共用程式的地方。


加入了 cron 目錄，這是用來存放排程程式的地方。


加入了 tmp 目錄，視需要使用。 


每個模組裡加入了 caches 資料夾，用來存放各模組所產生的快取資料。


註：以上的特色是在累積了多個 Zend Framework 專案經驗後所得出的結論，但或許各位所開發的專案屬性會和我的不同，因此這些特色僅供參考。
結論
Zend Framework 目錄結構的安排其實有很大的學問，在規劃得當的情況下，它能為我們帶來事半功倍的開發效率。本文簡單地為大家分析了幾種常見的目錄結構，也說明了它們的一些優缺點。各位朋友不妨多參考其他版本的目錄結構，並在瞭解專案的屬性後，選擇一個適合專案的目錄結構。
希望這篇文章能為各位在學習 Zend Framework 時帶來一些幫助，同時也希望對 Framework 有深入研究的朋友也能不吝指正我的謬誤。
	]]>
	</description>
	<content:encoded><![CDATA[
	<p>Zend Framework 目錄結構的安排 (Directory Layout) 也是一個很讓初學者困擾的問題，而且不論是官方或是社群都推薦了很多方法，更讓剛接觸 Zend Framework 的朋友難以適從。</p>
<p>本文將探討 Zend Framework 目錄結構的特點以及幾個常見的目錄結構，讓各位開發者能夠對它們有所認知。</p>
<h2>為什麼要有目錄結構</h2>
<p>目錄結構主要目的如下：</p>
<ul>
<li>
<p>將程式及相關文件分門別類，以便於管理。</p>
</li>
<li>
<p>便於設定相關存取權限。</p>
</li>
<li>
<p>讓開發者很快能找到要修改的檔案。</p>
</li>
</ul>
<p>因此選定一個好的目錄結構，將會為你的專案開發帶來高效率且易維護等好處。</p>
<h2>專案目錄要放在哪裡</h2>
<p>有些目錄結構需要有修改 Apache httpd.conf 的權限，有些則不需要；也因此專案目錄的存放位置也變得很重要，因為這會牽扯到安全性的問題。</p>
<p>一般來說，需要修改 httpd.conf 權限的目錄結構類型，我們可以放在檔案系統的任何地方，並確定它能讓 Apache 正確存取與執行。而不需要修改 httpd.conf 的類型，通常是為了因應專案的可攜性或是開發者缺少系統管理權；這時專案目錄就要放在 Apache 預設提供可以存取的位置，例如 /home/username/htdocs 。 </p>
<h2>常見的目錄結構</h2>
<p>以下我們來看看幾個常見的目錄結構。</p>
<h3>類型一：官方手冊的版本</h3>
<p>官方手冊的「 <a href="http://framework.zend.com/manual/en/zend.controller.html#zend.controller.quickstart">7.1. Zend_Controller Quick Start</a> 」一節裡提供了一個參考用的 Directory Layout ，我稍微做了一些修改，如下：</p>
<pre><code>application/
    controllers/
        IndexController.php
        ErrorController.php
    models/
    views/
        scripts/
            index/
                index.phtml
            error/
                error.phtml
        helpers/
        filters/
library/
    Zend/
    (other libraries)/
html/
    scripts/
    images/
    styles/
    .htaccess (導向 index.php)
    index.php</code></pre>
<h4>說明</h4>
<p>這是一個需要修改 httpd.conf 的目錄結構，也僅適用於單一功能的應用程式 (也就是單一模組) 。在安裝時我們必須修改 httpd.conf ，將專案的 Document Root 指向 html 這個目錄。 html 目錄除了做為 Document Root 外，其目地就是存放可公開的檔案，像是圖片、 JavaScript 或樣式表等等。而 application 目錄即為預設的模組，存放著 MVC 等三種類型的檔案 (即 controllers 、 models 及 views 等三個目錄) 。至於 library 目錄就比較隨意，我們只要確定它的執行權限，並且讓 PHP 能夠找到裡面所需要的類別即可。 </p>
<p>在預設模組中， controllers 目錄裡的 IndexController.php 與 ErrorController.php 都是一定要的，另外 views/scripts/index/index.phtml 和 views/scripts/error/error.phtml 也是如此；而原因可以參考 <a href="http://blog.roodo.com/jaceju/archives/5602901.html">Front Controller 的基本應用技</a>一文，這裡不再詳述。</p>
<p>這裡要特別說明 application/views 這個目錄，其中還區分成 scripts 、 helpers 及 filters 三個目錄。 scripts 主要放的就是 templates ，底下可以用小寫的 controller name 做為資料夾名稱以做為區別；而 helpers 和 filters 其實在實際應用上比較少用，所以通常我會把它們從結構中拿掉。</p>
<p class="note">註：為了節省篇幅，在呈現目錄結構時，預設模組的相關必要檔案我會略掉，但實際應用時請記得加回去。 </p>
<p>另外 .htaccess (導向 index.php) 的實際內容如下：</p>
<pre><code>RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
php_flag magic_quotes_gpc off
php_flag register_globals off </code></pre>
<p>在 .htaccess 的第一行中，由於 Zend Framework 支援自訂網址的功能，所以我們啟用了 RewriteEngine ，也就是設定為 on 。接著第二行我們加入一個 RewriteRule ，讓 index.php 處理所有非公開資源的 request 。</p>
<p class="note">註：不過 Zend Framework 也支援沒有 mod_rewrite 的環境，我們只要在 Front Controller 中將 baseUrl 設定好就沒問題了，這點有機會再探討。</p>
<p>剩下兩行是 PHP 的設定，這邊就不再加以說明。</p>
<p>這種目錄結構最大的特色是將 index.php 放在 html 目錄下， 這樣的好處在於能提高對 application 目錄的安全掌控度，因為 application 目錄並不會直接曝露給外部的瀏覽者。但是這樣的結構也有一個很大的缺點，那就是可攜性很差！換句話說如果在測試環境所使用的網址是 http://localhost/myproject/ ，而正式上線的環境卻是 http://www.myproject.com/ ，那麼就要修改 httpd.conf 讓 html 目錄對應到正確的網址，這樣才有辦法讓程式正確執行。 </p>
<h3>類型二： Rob Allen 的版本</h3>
<p>在 Rob 的 <a href="http://akrabat.com/zend-framework-tutorial/">Getting Started with the Zend Framework</a> 一文中，他採用了和官方不同的目錄結構：</p>
<pre><code>application/
    .htaccess (deny from all)
    controllers/
    models/
    views/
        filters/
        helpers/
        scripts/
library/
    Zend/
    (other libraries)/
    .htaccess (deny from all)
public/
    .htaccess (RewriteEngine off)
    images/
    scripts/
    styles/
.htaccess (導向 index.php)
index.php</code></pre>
<h4>說明</h4>
<p>這種目錄結構也是屬於單一功能 (模組) 的類型，它的特色是不必在 httpd.conf 中指定 Document Root 。這種目錄結構將 application 、 library 、 public (即第一種版本的 html) 以及 index.php 放在同一層的專案根目錄下，再利用 .htaccess 去控制每個目錄結構的存取權。 </p>
<p>.htaccess (導向 index.php) 內容和官方版相同，請參考上面的說明。比較特別的是 application/.htacess 的內容為 deny from all ，這是要避免用戶直接從網址瀏覽 application 內的檔案；而 public/.htaccess 的內容則是 RewriteEngine off ，亦即關閉原本 .htaccess (導向 index.php) 對此目錄的影響，讓用戶可以直接瀏覽 public 內的檔案 (就是圖片、 JavaScript 及樣式表等等) 。 </p>
<p>index.php 則是從 public 目錄中往外移至專案根目錄，這樣就可以讓用戶直接存取 (因為一般我們會在 Apache 設定 index.php 為預設執行頁) 。</p>
<p>這種目錄結構剛好和官方版本相反，它非常俱有可攜性，也是一般開發 Zend Framework 專案常用的目錄結構型態。不過它也有很大的缺點，那就是當 mod_rewrite 被關閉或是 .htaccess 不被解析時，這種目錄會將 application 及 library 兩個目錄曝露出來，在安全性上就大打折扣；不過通常這樣的 httpd.conf 設定比較少見，也因此一般開發 Zend Framework 專案時，大多都會採用這種目錄結構。 </p>
<h3>類型三： Gavin Vess 的 Conventional Modular 版本</h3>
<p>前面兩種版本都是單一功能 (模組) ，不過如果專案需要前後台或多種功能時，通常就會使用模組機制。Zend Framework 支援了模組機制，因此在目錄結構上也需要做一些改變。</p>
<p>有一篇 Gavin Vess 所寫的 <a href="http://framework.zend.com/wiki/display/ZFDEV/Choosing+Your+Application%27s+Directory+Layout">Choosing Your Application's Directory Layout</a> 也討論到了有關 Zend Framework 在模組上的目錄結構安排。文章中有個 Conventional Modular 版本，我也做稍做了修改，如下： </p>
<pre><code>application/
    config/ (非必要)
    default/
        config/ (非必要)
        controllers/
        models/
        views/
    (module 1)/
        controllers/
        models/
        views/
    (module 2)/
        controllers/
        models/
        views/
htdocs/
    images/
    scripts/
    styles/
    .htaccess (導向 index.php)
    index.php
library/
    Zend/
    (other libraries)/
tmp/
    sessions/
    cache/
    view_compiles/</code></pre>
<h4>說明</h4>
<p>很明顯地，這個版本是從官方版本演化而來的；它的主要特色是將原來 application 中的 MVC 三個目錄拿掉了，取而代之的是 default 、 module1 、 module2 等 MVC 模組。 </p>
<p>前面兩個版本都是以 application 為預設模組，因此我們不必在程式裡特別設定。但是在多模組的狀況下，我們需要指定 application 下的某個模組為預設模組；這部份的程式碼可以參考我在 「<a href="http://blog.roodo.com/jaceju/archives/5602901.html">Front Controller 的基本應用技</a>」一文中所提到的「進階的 Front Controller 用法」。 </p>
<p>其他的目錄也都能望名生義，這裡不再解說。</p>
<h3>類型四：我的版本</h3>
<p>最後介紹我自己所採用的版本。基本上它可以算是模組化的 Rob 版本，只是我為了專案開發需求，又再加入一些特別的目錄結構。 </p>
<pre><code>app/
    .htaccess (deny from all)
    base/
    cron/
    etc/
    lib/
    tmp/
    mod/
        default/
            caches/
            controllers/
            models/
            views/
        (module 1)/
            caches/
            controllers/
            models/
            views/
        (module 2)/
            caches/
            controllers/
            models/
            views/
pub/
    .htaccess (RewriteEngine off)
    img/
    js/
    css/
.htaccess (導向 index.php)
index.php</code></pre>
<h4>說明</h4>
<p>首先我將 application 及 public 的名稱分別縮短為 app 及 pub ，其它目錄名稱也改為較短的名稱。而所有的 .htaccess 則和 Rob 版的相同，因此也會有同樣的限制。 </p>
<p>另外我把放置 Zend Framwork 及其他 library 所在的 lib 目錄移入 app 目錄中以方便管理，  Gavin Vess 的 config 我也改成了 etc ，這點算是仿照 Gavin Vess 的 Classical (Unix/Linux-like) 版本。</p>
<p>其他幾個特點如下：</p>
<ol>
<li>
<p>加入了 base 目錄，這是用來存放專案共用程式的地方。</p>
</li>
<li>
<p>加入了 cron 目錄，這是用來存放排程程式的地方。</p>
</li>
<li>
<p>加入了 tmp 目錄，視需要使用。 </p>
</li>
<li>
<p>每個模組裡加入了 caches 資料夾，用來存放各模組所產生的快取資料。</p>
</li>
</ol>
<p class="note">註：以上的特色是在累積了多個 Zend Framework 專案經驗後所得出的結論，但或許各位所開發的專案屬性會和我的不同，因此這些特色僅供參考。</p>
<h2>結論</h2>
<p>Zend Framework 目錄結構的安排其實有很大的學問，在規劃得當的情況下，它能為我們帶來事半功倍的開發效率。本文簡單地為大家分析了幾種常見的目錄結構，也說明了它們的一些優缺點。各位朋友不妨多參考其他版本的目錄結構，並在瞭解專案的屬性後，選擇一個適合專案的目錄結構。</p>
<p>希望這篇文章能為各位在學習 Zend Framework 時帶來一些幫助，同時也希望對 Framework 有深入研究的朋友也能不吝指正我的謬誤。</p>		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/5611237.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/5611237.html</guid>
	<category>Zend Framework</category>
	<pubDate>Fri, 29 Feb 2008 00:30:51 +0800</pubDate>
</item>
<item>
	<title>[PHP-ZF] Front Controller 的基本應用技</title>
	<description><![CDATA[
	剛學 Zend Framework 的朋友通常會遇到兩個麻煩：目錄結構的安排，還有就是怎麼在 index.php (bootstrap) 中使用 Front Controller ？
目錄結構的安排下次有機會再談，這裡我來說說 Front Controller 的用法。
註：在此之前，請大家先看過 Rob Allen 寫的 Getting Started with the Zend Framework 一文 (PDF 版本) ；本文將會以該篇教學為基礎，一步一步來說明。 
什麼是 Front Controller 
整體而言 Front Controller 比較像是一個中介的角色，以下是它常見的幾個功能：


處理應用程式的初始化設定並執行之。


管理應用程式執行路徑。


管理輸入 (Request) ，使得使用者的動作得以分派 (&nbsp;Dispatch) 到 Action Controller 中。


管理輸出 (Response) ，使得應用程式能將結果傳送出來。


可以接受 Plugins 來擴充 Front Controller 的行為。


 Front Controller 裡還有更深入的參數設定機制，不過本文暫且先略過不談。 
基本的 Front Controller 用法 
我們先來看看 Rob 在 Getting Started with the Zend Framework 裡是怎麼用 Front Controller 的： 
&lt;?php
error_reporting(E_ALL|E_STRICT);
date_default_timezone_set('Europe/London');
set_include_path('.' . PATH_SEPARATOR . './library'
. PATH_SEPARATOR . './application/models/'
. PATH_SEPARATOR . get_include_path());

include &quot;Zend/Loader.php&quot;;
Zend_Loader::loadClass('Zend_Controller_Front');

// setup controller
$frontController = Zend_Controller_Front::getInstance();
$frontController-&gt;throwExceptions(true);
$frontController-&gt;setControllerDirectory('./application/controllers');

// run!
$frontController-&gt;dispatch();
撇開前面 PHP 的設定部份，我們可以看到 Front Controller 主要分成設定與執行兩個部份。
在設定的部份裡，首先我們可以看到 Front Controller 為 Singleton ，換句話說 Front Controller 在整個應用程式執行的過程中只會有一個實體存在。接著我們再呼叫 Front Controller 的 throwExceptions() 方法，它能為我們設定是否要將 Exception 直接丟出或是放到 Response 物件中。最後我們再設定應用程式的 Action Controller 所在路徑，讓 Front Controller 知道到哪裡能找到要執行的 action 。
當設定好 Front Controller 後，就可以呼叫它的 dispatch() 方法來執行整個應用程式了。
以上就是最簡單的 Front Controller 使用方法，接下來我會介紹目前我所使用的方法。 
進階的 Front Controller 用法 
先來看看程式碼：
&lt;?php
error_reporting(E_ALL|E_STRICT);
date_default_timezone_set('Asia/Taipei');

// set include_path
define('ROOT_PATH', str_replace('\\', '/', dirname(__FILE__)));
$includePath = array(
    ROOT_PATH . '/lib',
    get_include_path(),
);
set_include_path(join(PATH_SEPARATOR, $includePath));

// autoload
require_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();

// setup controller
$frontController = Zend_Controller_Front::getInstance();
$frontController-&gt;setControllerDirectory(array(
                      'default' =&gt; './app/mod/default/controllers',
                      'admin'   =&gt; './app/mod/admin/controllers'))
                -&gt;throwExceptions(false)
                -&gt;setDefaultModule('default')
                -&gt;returnResponse(true);

// run!
$response = $frontController-&gt;dispatch();
if ($response-&gt;isException()) {
    $response-&gt;renderExceptions(true);
}
$response-&gt;sendResponse();
基本上我在 PHP 一般設定的部份和 Rob 的差不多 (因為我也是從他的教學入門的) ，只是我在載入類別的地方做了一些修改而已 (例如自動載入) 。
設定部份
接下來我們來看 Front Controller 設定的部份：
// setup controller
$frontController = Zend_Controller_Front::getInstance();
$frontController-&gt;setControllerDirectory(array(
                      'default' =&gt; './app/mod/default/controllers',
                      'admin'   =&gt; './app/mod/admin/controllers'))
                -&gt;setDefaultModule('default')
                -&gt;throwExceptions(false)
                -&gt;returnResponse(true);
在 Rob 的教學中因為只需要單一的功能 (也就是專輯管理) ，因此他並沒有使用 Front Controller 的模組設定。而在我所開發的專案中通常會有前後台之分，因此我就應用了 Front Controller 裡的模組功能。使用 Front Controller 模組功能的方法很簡單，就是在 setControllerDirectory() 方法中，給它一個陣列參數；這個陣列參數的 key 即為模組名稱， value 則為模組中 Action Controller 的路徑。
然後我們要設定預設執行的模組，這裡使用的是 setDefaultModule() 方法。預設模組的好處是我們在網址上不必特別指定模組名稱，在上面的例子中即為 default 。如果不是預設的模組，那麼就要在網址中明確指定模組名稱；以 admin 這個模組來說，網址就要輸入： http://localhost/admin 。特別要注意的是網址上的模組名稱參考的是前段說明中的 key ，而非 value 裡的目錄名稱。 
接下來的 throwExceptions() 方法是個 setter 和 getter 的合體，當我們給它參數值時 (true 或 false) 它就是 setter ，反之不提供任何參數時就會是 getter 。前面提到 throwExceptions() 在設定  true 值時， Front Controller 會直接丟出 Exception ，這時程式就會直接中斷 (或是用 try...catch 來接也行) ；而 throwExceptions() 設定 false 值時，  Front Controller 則會將 Exception 放到 Response 物件裡，在稍後處理 Reponse 物件時才會看到 Exception 的內容。
註： throwExceptions() 方法在 setter 時會回傳 Front Controller 物件本身，而成為 getter 時則會回傳 boolean 值；這邊要特別小心，我也曾經在這裡中招。 
最後的 returnResponse() 方法也是個 setter 與 getter 的合體，它主要是設定 Front Controller 的 dispatch() 方法要不要回傳一個 Response 物件。這裡我的做法是永遠回傳 Response 物件 (也就是設定 true 值) ，這樣後面執行的程式碼才不會發生錯誤。 
執行部份
// run!
$response = $frontController-&gt;dispatch();
if ($response-&gt;isException()) {
    $response-&gt;renderExceptions(true);
}
$response-&gt;sendResponse();
在執行的部份，由於我們前面已經用 returnResponse() 方法來設定要回傳 Response 物件，因此 Front Controller 在完成 dispatch() 方法後就會將輸出的結果包裝在 Response 物件中回傳給 index.php 。
接著我們從 Response 物件的 isException() 方法來判斷輸出的結果是不是一個 Exception ，是的話就透過 Response 物件的 renderExceptions() 方法設定是否要顯示 Exception 。如果在這裡 renderExceptions() 方法的參數被設定為 false 時，那麼 Front Controller 就會呼叫預設模組底下 ErrorController 中的 errorAction() 方法，這樣就不會讓前端的瀏覽者看到程式錯誤，而是我們自訂的錯誤頁。
註：這個功能在上線環境中特別重要，你可以在這裡用 Response 物件的 getException() 方法取得 Exception 的內容然後寫入 Log 中，而最後只顯示自訂的 Error 頁面。
最後我們再呼叫 Response 物件的 sendResponse() 方法來將輸出的結果傳送給瀏覽器或 Console ，不論它是不是個 Exception 。
結論
以往我們在寫程式時，最頭痛的就是一開始的流程要怎麼寫？程式出現錯誤時要如何呈現？上線環境和開發環境要如何區別？而 Front Controller 正好為我們解決了許多這樣的麻煩；不過相對的它的使用方式也容易讓一般開發者感到迷惑，很多剛接觸的朋友就會在這裡受到很多挫折 (我剛好也是其中之一) 。 
其實 Zend Framework 的 Front Controller 是非常靈活且強大的，這裡僅僅只介紹了它的基本應用方式。後面如果有空的話，我會再介紹其他相關的功能。 
範例下載
照慣例，範例的下載位址在這裡。 

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>剛學 Zend Framework 的朋友通常會遇到兩個麻煩：目錄結構的安排，還有就是怎麼在 index.php (bootstrap) 中使用 Front Controller ？</p>
<p>目錄結構的安排下次有機會再談，這裡我來說說 Front Controller 的用法。</p>
<p class="note">註：在此之前，請大家先看過 Rob Allen 寫的 <a href="http://akrabat.com/zend-framework-tutorial/">Getting Started with the Zend Framework</a> 一文 (<a href="http://akrabat.com/wp-content/uploads/getting-started-with-the-zend-framework_145.pdf">PDF 版本</a>) ；本文將會以該篇教學為基礎，一步一步來說明。 </p>
<h2>什麼是 Front Controller </h2>
<p>整體而言 Front Controller 比較像是一個中介的角色，以下是它常見的幾個功能：</p>
<ol>
<li>
<p>處理應用程式的初始化設定並執行之。</p>
</li>
<li>
<p>管理應用程式執行路徑。</p>
</li>
<li>
<p>管理輸入 (Request) ，使得使用者的動作得以分派 (&nbsp;Dispatch) 到 Action Controller 中。</p>
</li>
<li>
<p>管理輸出 (Response) ，使得應用程式能將結果傳送出來。</p>
</li>
<li>
<p>可以接受 Plugins 來擴充 Front Controller 的行為。</p>
</li>
</ol>
<p> Front Controller 裡還有更深入的參數設定機制，不過本文暫且先略過不談。 </p>
<h2>基本的 Front Controller 用法 </h2>
<p>我們先來看看 Rob 在 <a href="http://akrabat.com/zend-framework-tutorial/">Getting Started with the Zend Framework</a> 裡是怎麼用 Front Controller 的： </p>
<pre><code>&lt;?php
error_reporting(E_ALL|E_STRICT);
date_default_timezone_set('Europe/London');
set_include_path('.' . PATH_SEPARATOR . './library'
. PATH_SEPARATOR . './application/models/'
. PATH_SEPARATOR . get_include_path());

include &quot;Zend/Loader.php&quot;;
Zend_Loader::loadClass('Zend_Controller_Front');

// setup controller
$frontController = Zend_Controller_Front::getInstance();
$frontController-&gt;throwExceptions(true);
$frontController-&gt;setControllerDirectory('./application/controllers');

// run!
$frontController-&gt;dispatch();</code></pre>
<p>撇開前面 PHP 的設定部份，我們可以看到 Front Controller 主要分成設定與執行兩個部份。</p>
<p>在設定的部份裡，首先我們可以看到 Front Controller 為 Singleton ，換句話說 Front Controller 在整個應用程式執行的過程中只會有一個實體存在。接著我們再呼叫 Front Controller 的 throwExceptions() 方法，它能為我們設定是否要將 Exception 直接丟出或是放到 Response 物件中。最後我們再設定應用程式的 Action Controller 所在路徑，讓 Front Controller 知道到哪裡能找到要執行的 action 。</p>
<p>當設定好 Front Controller 後，就可以呼叫它的 dispatch() 方法來執行整個應用程式了。</p>
<p>以上就是最簡單的 Front Controller 使用方法，接下來我會介紹目前我所使用的方法。 </p>
<h2>進階的 Front Controller 用法 </h2>
<p>先來看看程式碼：</p>
<pre><code>&lt;?php
error_reporting(E_ALL|E_STRICT);
date_default_timezone_set('Asia/Taipei');

// set include_path
define('ROOT_PATH', str_replace('\\', '/', dirname(__FILE__)));
$includePath = array(
    ROOT_PATH . '/lib',
    get_include_path(),
);
set_include_path(join(PATH_SEPARATOR, $includePath));

// autoload
require_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();

// setup controller
$frontController = Zend_Controller_Front::getInstance();
$frontController-&gt;setControllerDirectory(array(
                      'default' =&gt; './app/mod/default/controllers',
                      'admin'   =&gt; './app/mod/admin/controllers'))
                -&gt;throwExceptions(false)
                -&gt;setDefaultModule('default')
                -&gt;returnResponse(true);

// run!
$response = $frontController-&gt;dispatch();
if ($response-&gt;isException()) {
    $response-&gt;renderExceptions(true);
}
$response-&gt;sendResponse();</code></pre>
<p class="note">基本上我在 PHP 一般設定的部份和 Rob 的差不多 (因為我也是從他的教學入門的) ，只是我在載入類別的地方做了一些修改而已 (例如自動載入) 。</p>
<h3>設定部份</h3>
<p>接下來我們來看 Front Controller 設定的部份：</p>
<pre><code>// setup controller
$frontController = Zend_Controller_Front::getInstance();
$frontController-&gt;setControllerDirectory(array(
                      'default' =&gt; './app/mod/default/controllers',
                      'admin'   =&gt; './app/mod/admin/controllers'))
                -&gt;setDefaultModule('default')
                -&gt;throwExceptions(false)
                -&gt;returnResponse(true);</code></pre>
<p>在 Rob 的教學中因為只需要單一的功能 (也就是專輯管理) ，因此他並沒有使用 Front Controller 的模組設定。而在我所開發的專案中通常會有前後台之分，因此我就應用了 Front Controller 裡的模組功能。使用 Front Controller 模組功能的方法很簡單，就是在 setControllerDirectory() 方法中，給它一個陣列參數；這個陣列參數的 key 即為模組名稱， value 則為模組中 Action Controller 的路徑。</p>
<p>然後我們要設定預設執行的模組，這裡使用的是 setDefaultModule() 方法。預設模組的好處是我們在網址上不必特別指定模組名稱，在上面的例子中即為 default 。如果不是預設的模組，那麼就要在網址中明確指定模組名稱；以 admin 這個模組來說，網址就要輸入： http://localhost/admin 。特別要注意的是網址上的模組名稱參考的是前段說明中的 key ，而非 value 裡的目錄名稱。 </p>
<p>接下來的 throwExceptions() 方法是個 setter 和 getter 的合體，當我們給它參數值時 (true 或 false) 它就是 setter ，反之不提供任何參數時就會是 getter 。前面提到 throwExceptions() 在設定  true 值時， Front Controller 會直接丟出 Exception ，這時程式就會直接中斷 (或是用 try...catch 來接也行) ；而 throwExceptions() 設定 false 值時，  Front Controller 則會將 Exception 放到 Response 物件裡，在稍後處理 Reponse 物件時才會看到 Exception 的內容。</p>
<p class="note">註： throwExceptions() 方法在 setter 時會回傳 Front Controller 物件本身，而成為 getter 時則會回傳 boolean 值；這邊要特別小心，我也曾經在這裡中招。 </p>
<p>最後的 returnResponse() 方法也是個 setter 與 getter 的合體，它主要是設定 Front Controller 的 dispatch() 方法要不要回傳一個 Response 物件。這裡我的做法是永遠回傳 Response 物件 (也就是設定 true 值) ，這樣後面執行的程式碼才不會發生錯誤。 </p>
<h3>執行部份</h3>
<pre><code>// run!
$response = $frontController-&gt;dispatch();
if ($response-&gt;isException()) {
    $response-&gt;renderExceptions(true);
}
$response-&gt;sendResponse();</code></pre>
<p>在執行的部份，由於我們前面已經用 returnResponse() 方法來設定要回傳 Response 物件，因此 Front Controller 在完成 dispatch() 方法後就會將輸出的結果包裝在 Response 物件中回傳給 index.php 。</p>
<p>接著我們從 Response 物件的 isException() 方法來判斷輸出的結果是不是一個 Exception ，是的話就透過 Response 物件的 renderExceptions() 方法設定是否要顯示 Exception 。如果在這裡 renderExceptions() 方法的參數被設定為 false 時，那麼 Front Controller 就會呼叫預設模組底下 ErrorController 中的 errorAction() 方法，這樣就不會讓前端的瀏覽者看到程式錯誤，而是我們自訂的錯誤頁。</p>
<p class="note">註：這個功能在上線環境中特別重要，你可以在這裡用 Response 物件的 getException() 方法取得 Exception 的內容然後寫入 Log 中，而最後只顯示自訂的 Error 頁面。</p>
<p>最後我們再呼叫 Response 物件的 sendResponse() 方法來將輸出的結果傳送給瀏覽器或 Console ，不論它是不是個 Exception 。</p>
<h2>結論</h2>
<p>以往我們在寫程式時，最頭痛的就是一開始的流程要怎麼寫？程式出現錯誤時要如何呈現？上線環境和開發環境要如何區別？而 Front Controller 正好為我們解決了許多這樣的麻煩；不過相對的它的使用方式也容易讓一般開發者感到迷惑，很多剛接觸的朋友就會在這裡受到很多挫折 (我剛好也是其中之一) 。 </p>
<p>其實 Zend Framework 的 Front Controller 是非常靈活且強大的，這裡僅僅只介紹了它的基本應用方式。後面如果有空的話，我會再介紹其他相關的功能。 </p>
<h2>範例下載</h2>
<p>照慣例，範例的下載位址在<a href="http://www.jaceju.net/resources/zf_controller_front/front_controller.rar">這裡</a>。 </p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/5602901.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/5602901.html</guid>
	<category>Zend Framework</category>
	<pubDate>Wed, 27 Feb 2008 13:26:13 +0800</pubDate>
</item>
<item>
	<title>[PHP-ZF] 初探 Zend_Db_Table Relationships (三)</title>
	<description><![CDATA[
	前面我已經知道如何設定 Zend_Db_Table 的關連，這次來記一下串聯刪除 (cascading delete) 。
cascading delete 主要的目的是這樣的：假設 a 資料表和 b 資料表間有關連 (a.id = b.a_id) ，而當 a 資料表的某紀錄被刪除後，會使得 b 資料表中的相關紀錄失去作用而需要一併刪除。多數主流的資料庫系統都會內建類似的功能，例如 Oracle 、 MSSQL 及 PostgreSQL 等。但像是 MySQL 4.x 以前 的 MyISAM 格式並沒有提供 foreign key 和 trigger ，所以也沒辦法內建 Cascading Delete 時，這時只好從程式裡來著手。 
不過有一點要小心，就算資料庫系統有支援 cascading delete ，也必須在資料表定義 foreign key 時設定 cascading delete 的相關指令 (通常是 ON DELETE CASCADE) ；不然資料表還是不會知道要去刪掉對應的紀錄。
註：以上資訊有錯誤的話，煩請大家不吝指正。
延續上一次的程式碼，這次我要為它們加入 cascading delete 的功能。
範例下載
不提供了，請下載上次的範例照以下說明修改吧。
說明
刪除文章時同時刪除文章與標籤之間的關連
首先我們在 Articles 這個類別中，加入一個 $_dependentTables 屬性： 
&lt;?php

class Articles extends Zend_Db_Table_Abstract
{
    // ... 略 ...

    protected $_dependentTables = array('ArticlesTags');
}
這個  $_dependentTables 必須給它一個陣列，這個陣列要包含你要串聯刪除的資料表類別名稱 (此例即為 ArticlesTags 這個類別) 。
接下來打開 ArticlesTags 這個類別，在原本的 $_referenceMap['Article'] 關連中，再加入一個 onDelete 索引：
&lt;?php

class ArticlesTags extends Zend_Db_Table_Abstract
{
    protected $_referenceMap    = array(

        // ... 略 ...

        'Article' =&gt; array(
            'columns'           =&gt; array('article_id'),
            'refTableClass'     =&gt; 'Articles',
            'refColumns'        =&gt; 'id',
            'onDelete' =&gt; self::CASCADE,
        ),
    );
}
onDelete 的值固定就是用 self::CASCADE (其他值就不會動了) 。
註：別忘記原來 $_referenceMap['Article'] 所指定的意思，它是指 articles_tags 這個資料表的 articles_id (columns) 這個欄位要對應到 Articles (refTableClass) 這個資料表類別的 id 欄位 (refColumns) 。 
這樣設定好後，就完成串聯刪除的動作了，很簡單吧？不過有一點非常重要：那就是一定要用 Zend_Db_Table_Row 的 delete 方法來刪除紀錄，才能啟動串聯刪除！
舉個例子：假設現在有兩篇文章，標題分別是 jQuery 和 Prototype ；現在我為它們都下了 javascript 和 ajax 兩個標籤。現在資料表紀錄如下：

articles 資料表

id
category_id
title


3
2
jQuery


4
2
Prototype




tags 資料表


id
name


3
javascript


4
ajax




articles_tags 資料表


article_id
category_id


3
3


3
4


4
3


4
4


註：請依照上面的例子，先在 articles 、 tags 及 artices_tags 三個資料表分別加入相關的紀錄。 
接下來在 IndexController 中，加入一個 deleteAction 方法：
&lt;?php

class IndexController extends Zend_Controller_Action 
{
    // ... 略 ...

    function deleteAction()
    {
        // 不顯示畫面
        $this-&gt;getHelper('ViewRenderer')-&gt;setNoRender();
        $articleTable = new Articles();
        // 有找到才刪
        if ($articleRow = $articleTable-&gt;find(3)-&gt;current()) {
            $articleRow-&gt;delete();
        }
    }
}
現在瀏覽一下 http://localhost/example3/index/delete (實際位置請按照各位的環境自行輸入) ，畫面應該不會出現任何資訊。現在到資料庫觀察一下，應該會發現 articles 資料表的第 3 筆紀錄已經被刪除；再看看 articles_tags ，在 article_id 為 3 的紀錄也跟著一併被刪除了。這樣就完成串聯刪除啦！
再整理一次重點：


在要刪除紀錄的資料表類別裡定義 $_dependentTables 。


在要串聯刪除紀錄的資料表類別裡定義 $_referenceMap[關連的名稱] 的 onDelete 屬性。


要使用串聯刪除，一定要用 Zend_Db_Row 的 delete 方法。 



	]]>
	</description>
	<content:encoded><![CDATA[
	<p><a href="http://blog.roodo.com/jaceju/archives/4170901.html">前面我已經知道如何設定 Zend_Db_Table 的關連</a>，這次來記一下串聯刪除 (cascading delete) 。</p>
<p>cascading delete 主要的目的是這樣的：假設 a 資料表和 b 資料表間有關連 (a.id = b.a_id) ，而當 a 資料表的某紀錄被刪除後，會使得 b 資料表中的相關紀錄失去作用而需要一併刪除。多數主流的資料庫系統都會內建類似的功能，例如 Oracle 、 MSSQL 及 PostgreSQL 等。但像是 MySQL 4.x 以前 的 MyISAM 格式並沒有提供 foreign key 和 trigger ，所以也沒辦法內建 Cascading Delete 時，這時只好從程式裡來著手。 </p>
<p>不過有一點要小心，就算資料庫系統有支援 cascading delete ，也必須在資料表定義 foreign key 時設定 cascading delete 的相關指令 (通常是 ON DELETE CASCADE) ；不然資料表還是不會知道要去刪掉對應的紀錄。</p>
<p class="note">註：以上資訊有錯誤的話，煩請大家不吝指正。</p>
<p>延續上一次的程式碼，這次我要為它們加入 cascading delete 的功能。</p>
<h2>範例下載</h2>
<p>不提供了，請下載<a href="http://www.jaceju.net/resources/zf_table/example2.zip">上次的範例</a>照以下說明修改吧。</p>
<h2>說明</h2>
<h3>刪除文章時同時刪除文章與標籤之間的關連</h3>
<p>首先我們在 Articles 這個類別中，加入一個 $_dependentTables 屬性： </p>
<pre><code>&lt;?php

class Articles extends Zend_Db_Table_Abstract
{
    // ... 略 ...

    <strong>protected $_dependentTables = array('ArticlesTags');</strong>
}</code></pre>
<p>這個  $_dependentTables 必須給它一個陣列，這個陣列要包含你要串聯刪除的資料表類別名稱 (此例即為 ArticlesTags 這個類別) 。</p>
<p>接下來打開 ArticlesTags 這個類別，在原本的 $_referenceMap['Article'] 關連中，再加入一個 onDelete 索引：</p>
<pre><code>&lt;?php

class ArticlesTags extends Zend_Db_Table_Abstract
{
    protected $_referenceMap    = array(

        // ... 略 ...

        'Article' =&gt; array(
            'columns'           =&gt; array('article_id'),
            'refTableClass'     =&gt; 'Articles',
            'refColumns'        =&gt; 'id',
            <strong>'onDelete' =&gt; self::CASCADE,</strong>
        ),
    );
}</code></pre>
<p>onDelete 的值固定就是用 self::CASCADE (其他值就不會動了) 。</p>
<p class="note">註：別忘記原來 $_referenceMap['Article'] 所指定的意思，它是指 articles_tags 這個資料表的 articles_id (columns) 這個欄位要對應到 Articles (refTableClass) 這個資料表類別的 id 欄位 (refColumns) 。 </p>
<p>這樣設定好後，就完成串聯刪除的動作了，很簡單吧？不過有一點非常重要：那就是<strong>一定要用 Zend_Db_Table_Row 的 delete 方法來刪除紀錄，才能啟動串聯刪除！</strong></p>
<p>舉個例子：假設現在有兩篇文章，標題分別是 jQuery 和 Prototype ；現在我為它們都下了 javascript 和 ajax 兩個標籤。現在資料表紀錄如下：</p>
<table border="1" cellspacing="1" cellpadding="3" summary="articles 資料表" style="float:left; margin:10px;">
<caption>articles 資料表</caption>
<tr>
<th>id</th>
<th>category_id</th>
<th>title</th>
</tr>
<tr>
<td align="right">3</td>
<td align="right">2</td>
<td>jQuery</td>
</tr>
<tr>
<td align="right">4</td>
<td align="right">2</td>
<td>Prototype</td>
</tr>
</table>
<table border="1" cellspacing="1" cellpadding="3" summary="tags 資料表" style="float:left; margin:10px;">
<caption>
tags 資料表
</caption>
<tr>
<th>id</th>
<th>name</th>
</tr>
<tr>
<td align="right">3</td>
<td>javascript</td>
</tr>
<tr>
<td align="right">4</td>
<td>ajax</td>
</tr>
</table>
<table border="1" cellspacing="1" cellpadding="3" summary="articles_tags 資料表" style="float:left; margin:10px;">
<caption>
articles_tags 資料表
</caption>
<tr>
<th>article_id</th>
<th>category_id</th>
</tr>
<tr>
<td align="right">3</td>
<td align="right">3</td>
</tr>
<tr>
<td align="right">3</td>
<td align="right">4</td>
</tr>
<tr>
<td align="right">4</td>
<td align="right">3</td>
</tr>
<tr>
<td align="right">4</td>
<td align="right">4</td>
</tr>
</table>
<p class="note" style="clear:both;#height:1%;">註：請依照上面的例子，先在 articles 、 tags 及 artices_tags 三個資料表分別加入相關的紀錄。 </p>
<p>接下來在 IndexController 中，加入一個 deleteAction 方法：</p>
<pre><code>&lt;?php

class IndexController extends Zend_Controller_Action 
{
    // ... 略 ...

    function deleteAction()
    {
        // 不顯示畫面
        $this-&gt;getHelper('ViewRenderer')-&gt;setNoRender();
        $articleTable = new Articles();
        // 有找到才刪
        if ($articleRow = $articleTable-&gt;find(3)-&gt;current()) {
            $articleRow-&gt;delete();
        }
    }
}</code></pre>
<p>現在瀏覽一下 http://localhost/example3/index/delete (實際位置請按照各位的環境自行輸入) ，畫面應該不會出現任何資訊。現在到資料庫觀察一下，應該會發現 articles 資料表的第 3 筆紀錄已經被刪除；再看看 articles_tags ，在 article_id 為 3 的紀錄也跟著一併被刪除了。這樣就完成串聯刪除啦！</p>
<p>再整理一次重點：</p>
<ol>
<li>
<p>在要刪除紀錄的資料表類別裡定義 $_dependentTables 。</p>
</li>
<li>
<p>在要串聯刪除紀錄的資料表類別裡定義 $_referenceMap[關連的名稱] 的 onDelete 屬性。</p>
</li>
<li>
<p>要使用串聯刪除，一定要用 Zend_Db_Row 的 delete 方法。 </p>
</li>
</ol>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/4987039.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/4987039.html</guid>
	<category>Zend Framework</category>
	<pubDate>Tue, 15 Jan 2008 13:06:40 +0800</pubDate>
</item>
<item>
	<title>[PHP-ZF] Zend Framework 1.0.3 版釋出</title>
	<description><![CDATA[
	前陣子 Update SVN 時就發現了，昨天則正式公告。
這次釋出的 1.0.3 並沒有太大的功能更動，而是修正了一些在 1.0.2 發現的問題。詳細的更新情形請參考 ChangeLog 。 

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>前陣子 Update SVN 時就發現了，昨天則正式公告。</p>
<p>這次釋出的 1.0.3 並沒有太大的功能更動，而是修正了一些在 1.0.2 發現的問題。詳細的更新情形請參考 <a href="http://framework.zend.com/changelog">ChangeLog</a> 。 </p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/4565411.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/4565411.html</guid>
	<category>Zend Framework</category>
	<pubDate>Sat, 01 Dec 2007 10:31:50 +0800</pubDate>
</item>
<item>
	<title>[PHP-ZF] Zend Framework 1.0.2 版釋出</title>
	<description><![CDATA[
	這次 Zend Framework 1.0.2 主要是修正許多 1.0.1 所發現的 Bug ，詳細內容可以參考 Chagelog 。 
Zend_Gdata 修得最多，看來外國人還滿喜歡把 Google 的服務整合到程式裡面。 

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>這次 Zend Framework 1.0.2 主要是修正許多 1.0.1 所發現的 Bug ，詳細內容可以參考 <a href="http://framework.zend.com/changelog">Chagelog</a> 。 </p>
<p>Zend_Gdata 修得最多，看來外國人還滿喜歡把 Google 的服務整合到程式裡面。 </p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/4193807.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/4193807.html</guid>
	<category>Zend Framework</category>
	<pubDate>Wed, 26 Sep 2007 16:08:08 +0800</pubDate>
</item>
<item>
	<title>[PHP-ZF] 初探 Zend_Db_Table Relationships (二)</title>
	<description><![CDATA[
	前一篇文章提到了簡單的 Zend_Db_Table 的一對多關連，這次來談一對一 (多對一) 和多對多。
不過我對一對一的定義比較模糊，詳細的資訊請參考良葛格的 Hibernate 學習筆記：

一對一（唯一外鍵關聯）
一對一（主鍵關聯）
多對多

資料表範例
基本上還是前一篇文章的範例，這次加上標籤 (Tag) ；每篇文章 (Article) 可以標上多個標籤，而每個標籤則是可以對應到多篇文章。新增的資料表結構如下： 
CREATE TABLE IF NOT EXISTS `tags` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(200) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

INSERT INTO `tags` (`id`, `name`) VALUES
(1, 'php'),
(2, 'zend framework');

CREATE TABLE IF NOT EXISTS `articles_tags` (
  `article_id` int(10) unsigned NOT NULL default '0',
  `tag_id` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`article_id`,`tag_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO `articles_tags` (`article_id`, `tag_id`) VALUES
(1, 1),
(1, 2),
(2, 1),
(2, 2);
其中我們多了一個中間表 articles_tags ，然後在邏輯上 articles.id 會關連到 articles_tags.article_id ，而 tags.id 則對應到  articles_tags.tag_id 。在 articles_tags 中， article_id 和 tag_id 為組合主鍵。
範例下載 
下載位置
註：一樣沒包 Zend Framework ，請自行下載安裝。 
說明
一對一 (多對一) 
首先我們先來看看如何如何從文章中抓取對應的分類，從一篇文章上只會找到一個分類，也就是一對一關連。
註：其實嚴格來說文章對分類不是一對一的關係 (應該是多對一) ，只是在 Zend_Db_Table 裡，它們的作法是相似的。
然而一對多和多對一只是兩個相關的對應關係，因此我們並不用修改原來的 Articles 和 Categories 兩個 Classes 。在 Zend_Db_Table_Row 中，提供了一個 findParentRow 方法，讓我們能從 Articles 反推回去找到 Categories ；也就是在 IndexController::index 中，我們只要這樣做：
$phpArticle = $articles-&gt;find(2)-&gt;current();
$this-&gt;view-&gt;category = $phpArticle-&gt;findParentRow('Categories');
這裡會抓取 articles.id 等於 2 的文章，然後透過 findParentRow 來向 Categories 取得對應的分類。另外 Zend_Db_Table_Row 也提供了一個魔術方法，只要用 findParent&lt;ParentClass&gt; 就可以達到同樣的效果，例如：
$this-&gt;view-&gt;category = $phpArticle-&gt;findParentCategories();
然後我們就可以在 index.phtml 顯示相關的分類了：
&lt;?php
var_dump($this-&gt;category-&gt;toArray());
?&gt;
多對多 
文章和標籤是以多對多的關係存在的，所以我們要先加入兩個 Classes ，一個是 Tags ，另一個是 ArticlesTags ；它們分別對應 tags 和 articles_tags 兩個資料表：
class Tags extends Zend_Db_Table_Abstract
{
    protected $_name = 'tags';
}

class ArticlesTags extends Zend_Db_Table_Abstract
{
    protected $_name = 'articles_tags';

    protected $_referenceMap    = array(
        'Tag' =&gt; array(
            'columns'           =&gt; array('tag_id'),
            'refTableClass'     =&gt; 'Tags',
            'refColumns'        =&gt; 'id',
        ),
        'Article' =&gt; array(
            'columns'           =&gt; array('article_id'),
            'refTableClass'     =&gt; 'Articles',
            'refColumns'        =&gt; 'id',
        ),
    );
}
註：這裡暫時不考慮 $_dependentTables 屬性，後面有用到再加。 
在 ArticlesTags 這個 Class 的 $_referenceMap 屬性裡，我定義了兩個 Rule ，一個為 Tag 、另一個為 Article ；它們分別關連到 Tags 和 Articles 這兩個 Classes 。
在 Zend_Db_Table_Row 裡提供了一個 findManyToManyRowset 的方法，可以協助我們處理多對多的關係。我們沿續第一個例子，假設現在我們想知道該篇文章所對應的標籤有哪些，可以這樣寫：
$this-&gt;view-&gt;articleTags = $phpArticle-&gt;findManyToManyRowset('Tags', 'ArticlesTags', 'Article');
在 findManyToManyRowset 方法裡一般會用到三個參數，第一個參數表示要關連的資料表 Class ，第二個參數則是中間表所對應的 Class ，而第三個為 Rule 的名稱。而要特別注意的是， Rule 所對應的 refTableClass 要和 findManyToManyRowset 方法所在的物件其對應的資料表一樣。可以對照一下上面 $phpArticle 物件所對應的資料表和最後一個參數值 Article 所對應的資料表，這樣就很容易理解了。
最後一樣在 index.phtml 裡顯示結果： 
&lt;?php
var_dump($this-&gt;articleTags-&gt;toArray());
?&gt;
當然反過來要從標籤去取得文章也就很簡單了，只要抓出目前的標籤，然後再利用 findManyToManyRowset 方法來取得關連的文章就可以了 (提示： Rule 要用 Tag) 。 

	]]>
	</description>
	<content:encoded><![CDATA[
	<p><a href="http://blog.roodo.com/jaceju/archives/4167233.html">前一篇文章</a>提到了簡單的 Zend_Db_Table 的一對多關連，這次來談一對一 (多對一) 和多對多。</p>
<p>不過我對一對一的定義比較模糊，詳細的資訊請參考<a href="http://caterpillar.onlyfun.net/Gossip/HibernateGossip/HibernateGossip.html">良葛格的 Hibernate 學習筆記</a>：</p>
<ul>
<li><a href="http://caterpillar.onlyfun.net/Gossip/HibernateGossip/OneToOneUniqueFK.html">一對一（唯一外鍵關聯）</a></li>
<li><a href="http://caterpillar.onlyfun.net/Gossip/HibernateGossip/OneToOnePK.html">一對一（主鍵關聯）</a></li>
<li><a href="http://caterpillar.onlyfun.net/Gossip/HibernateGossip/ManyToMany.html">多對多</a></li>
</ul>
<h2>資料表範例</h2>
<p>基本上還是前一篇文章的範例，這次加上標籤 (Tag) ；每篇文章 (Article) 可以標上多個標籤，而每個標籤則是可以對應到多篇文章。新增的資料表結構如下： </p>
<pre><code>CREATE TABLE IF NOT EXISTS `tags` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(200) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

INSERT INTO `tags` (`id`, `name`) VALUES
(1, 'php'),
(2, 'zend framework');

CREATE TABLE IF NOT EXISTS `articles_tags` (
  `article_id` int(10) unsigned NOT NULL default '0',
  `tag_id` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`article_id`,`tag_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO `articles_tags` (`article_id`, `tag_id`) VALUES
(1, 1),
(1, 2),
(2, 1),
(2, 2);</code></pre>
<p>其中我們多了一個中間表 articles_tags ，然後在邏輯上 articles.id 會關連到 articles_tags.article_id ，而 tags.id 則對應到  articles_tags.tag_id 。在 articles_tags 中， article_id 和 tag_id 為組合主鍵。</p>
<h2>範例下載 </h2>
<p><a href="http://www.jaceju.net/resources/zf_table/example2.zip">下載位置</a></p>
<p class="note">註：一樣沒包 Zend Framework ，請自行下載安裝。 </p>
<h2>說明</h2>
<h3>一對一 (多對一) </h3>
<p>首先我們先來看看如何如何從文章中抓取對應的分類，從一篇文章上只會找到一個分類，也就是一對一關連。</p>
<p class="note">註：其實嚴格來說文章對分類不是一對一的關係 (應該是多對一) ，只是在 Zend_Db_Table 裡，它們的作法是相似的。</p>
<p>然而一對多和多對一只是兩個相關的對應關係，因此我們並不用修改原來的 Articles 和 Categories 兩個 Classes 。在 Zend_Db_Table_Row 中，提供了一個 findParentRow 方法，讓我們能從 Articles 反推回去找到 Categories ；也就是在 IndexController::index 中，我們只要這樣做：</p>
<pre><code>$phpArticle = $articles-&gt;find(2)-&gt;current();
$this-&gt;view-&gt;category = $phpArticle-&gt;findParentRow('Categories');</code></pre>
<p>這裡會抓取 articles.id 等於 2 的文章，然後透過 findParentRow 來向 Categories 取得對應的分類。另外 Zend_Db_Table_Row 也提供了一個魔術方法，只要用 findParent&lt;ParentClass&gt; 就可以達到同樣的效果，例如：</p>
<pre><code>$this-&gt;view-&gt;category = $phpArticle-&gt;findParent<strong>Categories</strong>();</code></pre>
<p>然後我們就可以在 index.phtml 顯示相關的分類了：</p>
<pre><code>&lt;?php
var_dump($this-&gt;category-&gt;toArray());
?&gt;</code></pre>
<h3>多對多 </h3>
<p>文章和標籤是以多對多的關係存在的，所以我們要先加入兩個 Classes ，一個是 Tags ，另一個是 ArticlesTags ；它們分別對應 tags 和 articles_tags 兩個資料表：</p>
<pre><code>class Tags extends Zend_Db_Table_Abstract
{
    protected $_name = 'tags';
}

class ArticlesTags extends Zend_Db_Table_Abstract
{
    protected $_name = 'articles_tags';

    protected $_referenceMap    = array(
        'Tag' =&gt; array(
            'columns'           =&gt; array('tag_id'),
            'refTableClass'     =&gt; 'Tags',
            'refColumns'        =&gt; 'id',
        ),
        'Article' =&gt; array(
            'columns'           =&gt; array('article_id'),
            'refTableClass'     =&gt; 'Articles',
            'refColumns'        =&gt; 'id',
        ),
    );
}</code></pre>
<p>註：這裡暫時不考慮 $_dependentTables 屬性，後面有用到再加。 </p>
<p>在 ArticlesTags 這個 Class 的 $_referenceMap 屬性裡，我定義了兩個 Rule ，一個為 Tag 、另一個為 Article ；它們分別關連到 Tags 和 Articles 這兩個 Classes 。</p>
<p>在 Zend_Db_Table_Row 裡提供了一個 findManyToManyRowset 的方法，可以協助我們處理多對多的關係。我們沿續第一個例子，假設現在我們想知道該篇文章所對應的標籤有哪些，可以這樣寫：</p>
<pre><code>$this-&gt;view-&gt;articleTags = $phpArticle-&gt;findManyToManyRowset(<strong>'Tags'</strong>, <strong>'ArticlesTags'</strong>, <strong>'Article'</strong>);</code></pre>
<p>在 findManyToManyRowset 方法裡一般會用到三個參數，第一個參數表示要關連的資料表 Class ，第二個參數則是中間表所對應的 Class ，而第三個為 Rule 的名稱。而要特別注意的是， Rule 所對應的 refTableClass 要和 findManyToManyRowset 方法所在的物件其對應的資料表一樣。可以對照一下上面 $phpArticle 物件所對應的資料表和最後一個參數值 Article 所對應的資料表，這樣就很容易理解了。</p>
<p>最後一樣在 index.phtml 裡顯示結果： </p>
<pre><code>&lt;?php
var_dump($this-&gt;articleTags-&gt;toArray());
?&gt;</code></pre>
<p>當然反過來要從標籤去取得文章也就很簡單了，只要抓出目前的標籤，然後再利用 findManyToManyRowset 方法來取得關連的文章就可以了 (提示： Rule 要用 Tag) 。 </p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/4170901.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/4170901.html</guid>
	<category>Zend Framework</category>
	<pubDate>Fri, 21 Sep 2007 00:09:43 +0800</pubDate>
</item>
<item>
	<title>[PHP-ZF] 初探 Zend_Db_Table Relationships (一)</title>
	<description><![CDATA[
	早上四點半就醒了...睡不著，想說研究一下 Zend Framework DB 一對多的關連。先前一直搞不定其中的關係，沒想到簡單玩了一下，竟然就搞定了 (可見手冊我根本就沒看懂...Orz) 。
這裡記一下，以免之後又忘記了。
資料表範例
這裡我用文章 (Article) 及文章分類 (Category) 來做為例子，它們的 DB Schema 如下：
CREATE TABLE IF NOT EXISTS `articles` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `category_id` int(10) unsigned NOT NULL,
  `title` varchar(200) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `table1_id` (`category_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

INSERT INTO `articles` (`id`, `category_id`, `title`) VALUES
(1, 3, 'Zend_Db_Table'),
(2, 3, 'Zend_Controller_Action'),
(3, 2, 'jQuery'),
(4, 2, 'Prototype');

CREATE TABLE IF NOT EXISTS `categories` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `parent_id` int(10) unsigned NULL,
  `name` varchar(200) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

INSERT INTO `categories` (`id`, `parent_id`, `name`) VALUES
(1, NULL, 'PHP'),
(2, NULL, 'JavaScript'),
(3, 1, 'Zend Framework');
其中 articles.category_id 對應到 categories.id ，而 categories.parent_id 也對應到自己的 categories.id 。
程式碼架構
這裡主要我是拿 Rob 的 Getting Started with the Zend Framework 裡面範例來修改，詳細架構就先看看後面附的下載檔。
不過也不一定需要用這樣的架構才能跑 ZF ，這是因為我偷懶不想寫太多不相關的程式，所以直接拿別人的來改。事實上我們可以把 Zend_Db 獨立出來使用，只是這樣要寫的東西就會比較複雜一點點，跟我要研究的東西無關。
範例下載
下載位置
註：裡面沒包 Zend Framework ，請自行到官方網站下載，然後把 library 目錄解開放到範例資料夾下即可。 
說明
首先我們需要兩個繼承 Zend_Db_Table_Abstract 的 Class ，它們分別是 Articles 和 Categories ：
class Articles extends Zend_Db_Table_Abstract
{
    protected $_name = 'articles';
}

class Categories extends Zend_Db_Table_Abstract
{
    protected $_name = 'categories';
}
因為大部份工作已經被 Zend_Db_Table_Abstract 做掉了，所以 Articles 和 Categories 只要很簡單的指定 $_name 屬性即可；這樣一來， Articles 和 Categories 兩個 Classes 就能對應到 articles 和 categories 兩個資料表。
不過這樣還沒有辦法讓這兩個資料表在程式碼裡產生關連，我們必須在  Articles 和 Categories 這兩個 Classes 額外定義一些資訊，讓它們能互相認識。首先我們在 Articles Class 裡加上 $_referenceMap 屬性：
class Articles extends Zend_Db_Table_Abstract
{
    protected $_name = 'articles';

    protected $_referenceMap    = array(
        'Category' =&gt; array( // 給這個關連一個名字
            'columns'           =&gt; 'category_id', // 對應到 articles.category_id
            'refTableClass'     =&gt; 'Categories',  // 對應到 Categories Class
            'refColumns'        =&gt; 'id',          // 對應到 categories.id
        ),
    );
}
$_referenceMap 屬性是用來宣告要透過哪個欄位來和另一個資料表做關連，就上面的例子來看，我們可以很清楚的看到是 articles.category_id 關連到 categories.id 。然而 $_referenceMap 屬性可以同時定義多組關連，但為了簡化以便於理解，這裡我只用了一組。
在這裡的 $_referenceMap 屬性裡主要有三個項目：


 columns ：表示目前資料表關連到另一個資料表的欄位，一般就是 Foreign Key (FK) 。


refTableClass ：關連資料表所對應的 Class ，這裡要注意大小寫。


refColumns ：關連資料表所對應的欄位，一般就是 Primary Key (PK) 。 


註： $_referenceMap 其實還有其他可設定的項目，這裡暫不介紹。 
接著 Categories 這個 Class 也必須定義一個 $_dependentTables 屬性，宣告與 categories 有關連的資料表名稱；這是為了保證我們在透過 Categories Class 刪除資料時，能一併刪掉關連資料表裡的資料 (這裡我還在研究，尚無實例) 。
class Categories extends Zend_Db_Table_Abstract
{
    protected $_name = 'categories';

    protected $_dependentTables = array('Articles');  // 對應到關連的 Table Class
}
註：事實上 $_dependentTables 屬性在目前這個例子裡可以不加，因為我們還用不到關連更新或刪除的功能。 
現在我們可以在 IndexController::indexAction 裡測試看看：
class IndexController extends Zend_Controller_Action 
{
    function indexAction()
    {
        $categories = new Categories();

        $zendframework = $categories-&gt;find(3)-&gt;current();
        $this-&gt;view-&gt;articles = $zendframework-&gt;findDependentRowset('Articles');
    }
}
其中 findDependentRowset 是 Zend_Db_Table_Abstract 提供的方法，它可以幫我們找出關連資料表的所有資料。我們在 index.pthml 裡可以將取得的結果表列出來： 
&lt;?php
var_dump($this-&gt;articles-&gt;toArray());
?&gt;
是不是很簡單呢？
那麼第二個問題來了，如果我們要讓 categories._parent_id 和 categories.id 產生關連呢？
其實仿照上面的做法，我們只需要在 Categories Class 裡動手腳即可：
class Categories extends Zend_Db_Table_Abstract
{
    protected $_name = 'categories';

    protected $_referenceMap    = array(
        'ParentCategory' =&gt; array(
            'columns'           =&gt; 'parent_id',   // 對應到 categories.parent_id
            'refTableClass'     =&gt; 'Categories',  // 對應到 Categories Class
            'refColumns'        =&gt; 'id',          // 對應到 categories.id
        ),
    );

    protected $_dependentTables = array('Articles', 'Categories');   // 對應到關連的 Table Class
}
也就是說，我們在 Categories Class 加入一個 $_referenceMap 屬性關連到自己，然後在  $_dependentTables 加入自己。 
接著在 IndexController::indexAction 中測試一下：
class IndexController extends Zend_Controller_Action 
{
    function indexAction()
    {
        $categories = new Categories();

        $php = $categories-&gt;find(1)-&gt;current();
        $this-&gt;view-&gt;subcategories = $php-&gt;findDependentRowset('Categories');

        $zendframework = $categories-&gt;find(3)-&gt;current();
        $this-&gt;view-&gt;articles = $zendframework-&gt;findDependentRowset('Articles');
    }
}
在 index.phtml 裡顯示結果：
&lt;?php
var_dump($this-&gt;subcategories-&gt;toArray());
?&gt;
以上就是簡單的 Zend_Db_Table_Actract 一對多關連取得資料集的方式，謝謝收看，下次見。 (補眠去...什麼？已經天亮要上班了喔？) 

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>早上四點半就醒了...睡不著，想說研究一下 Zend Framework DB 一對多的關連。先前一直搞不定其中的關係，沒想到簡單玩了一下，竟然就搞定了 (可見手冊我根本就沒看懂...Orz) 。</p>
<p>這裡記一下，以免之後又忘記了。</p>
<h2>資料表範例</h2>
<p>這裡我用文章 (Article) 及文章分類 (Category) 來做為例子，它們的 DB Schema 如下：</p>
<pre><code>CREATE TABLE IF NOT EXISTS `articles` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `category_id` int(10) unsigned NOT NULL,
  `title` varchar(200) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `table1_id` (`category_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

INSERT INTO `articles` (`id`, `category_id`, `title`) VALUES
(1, 3, 'Zend_Db_Table'),
(2, 3, 'Zend_Controller_Action'),
(3, 2, 'jQuery'),
(4, 2, 'Prototype');

CREATE TABLE IF NOT EXISTS `categories` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `parent_id` int(10) unsigned NULL,
  `name` varchar(200) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

INSERT INTO `categories` (`id`, `parent_id`, `name`) VALUES
(1, NULL, 'PHP'),
(2, NULL, 'JavaScript'),
(3, 1, 'Zend Framework');</code></pre>
<p>其中 articles.category_id 對應到 categories.id ，而 categories.parent_id 也對應到自己的 categories.id 。</p>
<h2>程式碼架構</h2>
<p>這裡主要我是拿 <a href="http://akrabat.com/">Rob</a> 的 <a href="http://akrabat.com/zend-framework-tutorial/">Getting Started with the Zend Framework</a> 裡面範例來修改，詳細架構就先看看後面附的下載檔。</p>
<p>不過也不一定需要用這樣的架構才能跑 ZF ，這是因為我偷懶不想寫太多不相關的程式，所以直接拿別人的來改。事實上我們可以把 Zend_Db 獨立出來使用，只是這樣要寫的東西就會比較複雜一點點，跟我要研究的東西無關。</p>
<h2>範例下載</h2>
<p><a href="http://www.jaceju.net/resources/zf_table/example1.zip">下載位置</a></p>
<p class="note">註：裡面沒包 Zend Framework ，請自行到<a href="http://framework.zend.com/">官方網站</a>下載，然後把 library 目錄解開放到範例資料夾下即可。 </p>
<h2>說明</h2>
<p>首先我們需要兩個繼承 Zend_Db_Table_Abstract 的 Class ，它們分別是 Articles 和 Categories ：</p>
<pre><code>class Articles extends Zend_Db_Table_Abstract
{
    protected $_name = 'articles';
}

class Categories extends Zend_Db_Table_Abstract
{
    protected $_name = 'categories';
}</code></pre>
<p>因為大部份工作已經被 Zend_Db_Table_Abstract 做掉了，所以 Articles 和 Categories 只要很簡單的指定 $_name 屬性即可；這樣一來， Articles 和 Categories 兩個 Classes 就能對應到 articles 和 categories 兩個資料表。</p>
<p>不過這樣還沒有辦法讓這兩個資料表在程式碼裡產生關連，我們必須在  Articles 和 Categories 這兩個 Classes 額外定義一些資訊，讓它們能互相認識。首先我們在 Articles Class 裡加上 $_referenceMap 屬性：</p>
<pre><code>class Articles extends Zend_Db_Table_Abstract
{
    protected $_name = 'articles';

    protected $_referenceMap    = array(
        'Category' =&gt; array( // 給這個關連一個名字
            'columns'           =&gt; 'category_id', // 對應到 articles.category_id
            'refTableClass'     =&gt; 'Categories',  // 對應到 Categories Class
            'refColumns'        =&gt; 'id',          // 對應到 categories.id
        ),
    );
}</code></pre>
<p>$_referenceMap 屬性是用來宣告要透過哪個欄位來和另一個資料表做關連，就上面的例子來看，我們可以很清楚的看到是 articles.category_id 關連到 categories.id 。然而 $_referenceMap 屬性可以同時定義多組關連，但為了簡化以便於理解，這裡我只用了一組。</p>
<p>在這裡的 $_referenceMap 屬性裡主要有三個項目：</p>
<ul>
<li>
<p> columns ：表示目前資料表關連到另一個資料表的欄位，一般就是 Foreign Key (FK) 。</p>
</li>
<li>
<p>refTableClass ：關連資料表所對應的 Class ，這裡要注意大小寫。</p>
</li>
<li>
<p>refColumns ：關連資料表所對應的欄位，一般就是 Primary Key (PK) 。 </p>
</li>
</ul>
<p class="note">註： $_referenceMap 其實還有其他可設定的項目，這裡暫不介紹。 </p>
<p>接著 Categories 這個 Class 也必須定義一個 $_dependentTables 屬性，宣告與 categories 有關連的資料表名稱；這是為了保證我們在透過 Categories Class 刪除資料時，能一併刪掉關連資料表裡的資料 (這裡我還在研究，尚無實例) 。</p>
<pre><code>class Categories extends Zend_Db_Table_Abstract
{
    protected $_name = 'categories';

    protected $_dependentTables = array('Articles');  // 對應到關連的 Table Class
}</code></pre>
<p class="note">註：事實上 $_dependentTables 屬性在目前這個例子裡可以不加，因為我們還用不到關連更新或刪除的功能。 </p>
<p>現在我們可以在 IndexController::indexAction 裡測試看看：</p>
<pre><code>class IndexController extends Zend_Controller_Action 
{
    function indexAction()
    {
        $categories = new Categories();

        $zendframework = $categories-&gt;find(3)-&gt;current();
        $this-&gt;view-&gt;articles = $zendframework-&gt;findDependentRowset('Articles');
    }
}</code></pre>
<p>其中 findDependentRowset 是 Zend_Db_Table_Abstract 提供的方法，它可以幫我們找出關連資料表的所有資料。我們在 index.pthml 裡可以將取得的結果表列出來： </p>
<pre><code>&lt;?php
var_dump($this-&gt;articles-&gt;toArray());
?&gt;</code></pre>
<p>是不是很簡單呢？</p>
<p>那麼第二個問題來了，如果我們要讓 categories._parent_id 和 categories.id 產生關連呢？</p>
<p>其實仿照上面的做法，我們只需要在 Categories Class 裡動手腳即可：</p>
<pre><code>class Categories extends Zend_Db_Table_Abstract
{
    protected $_name = 'categories';

    <strong>protected $_referenceMap    = array(</strong>
        <strong>'ParentCategory' =&gt; array(</strong>
            <strong>'columns'           =&gt; 'parent_id',   // 對應到 categories.parent_id</strong>
            <strong>'refTableClass'     =&gt; 'Categories',  // 對應到 Categories Class</strong>
            <strong>'refColumns'        =&gt; 'id',          // 對應到 categories.id</strong>
        <strong>),</strong>
    <strong>);</strong>

    protected $_dependentTables = array('Articles'<strong>, 'Categories'</strong>);   // 對應到關連的 Table Class
}</code></pre>
<p>也就是說，我們在 Categories Class 加入一個 $_referenceMap 屬性關連到自己，然後在  $_dependentTables 加入自己。 </p>
<p>接著在 IndexController::indexAction 中測試一下：</p>
<pre><code>class IndexController extends Zend_Controller_Action 
{
    function indexAction()
    {
        $categories = new Categories();

        <strong>$php = $categories-&gt;find(1)-&gt;current();</strong>
        <strong>$this-&gt;view-&gt;subcategories = $php-&gt;findDependentRowset('Categories');</strong>

        $zendframework = $categories-&gt;find(3)-&gt;current();
        $this-&gt;view-&gt;articles = $zendframework-&gt;findDependentRowset('Articles');
    }
}</code></pre>
<p>在 index.phtml 裡顯示結果：</p>
<pre><code>&lt;?php
var_dump($this-&gt;subcategories-&gt;toArray());
?&gt;</code></pre>
<p>以上就是簡單的 Zend_Db_Table_Actract 一對多關連取得資料集的方式，謝謝收看，下次見。 (補眠去...什麼？已經天亮要上班了喔？) </p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/4167233.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/4167233.html</guid>
	<category>Zend Framework</category>
	<pubDate>Thu, 20 Sep 2007 06:46:57 +0800</pubDate>
</item>
<item>
	<title>[PHP-ZF] Zend Framework 即將推出英文書</title>
	<description><![CDATA[
	Rob 帶來了一個好消息，那就是 Zend Framework 要出書囉！它叫： Zend Framework in Action 。 
這本書是 Rob Allen 和 Nick Lo 兩人合著的，大綱如下：
Part 1: The essentials

 1. Introducing the Zend Framework (試讀章節) 
2. Hello Zend Framework!

 Part 2: A core application

 3. Building a web site with the Zend Framework
 4. Ajax
 5. Managing the database
 6. User authentication and authorisation
 7. Forms
 8. Searching
 9. Email
 10. Deployment

 Part 3: More power to your application

 11. Talking with other applications
 12. Mash ups with public web services
 13. Caching: making it faster
 14. Internationalization and localization
 15. Creating PDFs
 16. Integrating with other PHP libraries


 Appendix A. Stuff you (should) already know
 Appendix B. System-specific gotchas
 Appendix C. Zend Framework Core Components reference

雖然大部份章節還在撰寫當中，不過真的好想買來看喔~~尤其第二部份介紹的是一些很常用的功能，絕對值得 ZF 開發者買來參考。 

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>Rob 帶來了一個好消息，那就是 <a href="http://framework.zend.com">Zend Framework</a> 要出書囉！它叫： <a href="http://www.manning.com/allen/">Zend Framework in Action</a> 。 </p>
<p>這本書是 <a href="http://akrabat.com/">Rob Allen</a> 和 <a href="http://www.ingredients.com.au/nick/">Nick Lo</a> 兩人合著的，大綱如下：</p>
<p>Part 1: The essentials</p>
<ul>
<li> 1. Introducing the Zend Framework (<a href="http://www.manning.com/allen/meap_allench1.pdf">試讀章節</a>) </li>
<li>2. Hello Zend Framework!</li>
</ul>
<p> Part 2: A core application</p>
<ul>
<li> 3. Building a web site with the Zend Framework</li>
<li> 4. Ajax</li>
<li> 5. Managing the database</li>
<li> 6. User authentication and authorisation</li>
<li> 7. Forms</li>
<li> 8. Searching</li>
<li> 9. Email</li>
<li> 10. Deployment</li>
</ul>
<p> Part 3: More power to your application</p>
<ul>
<li> 11. Talking with other applications</li>
<li> 12. Mash ups with public web services</li>
<li> 13. Caching: making it faster</li>
<li> 14. Internationalization and localization</li>
<li> 15. Creating PDFs</li>
<li> 16. Integrating with other PHP libraries</li>
</ul>
<ul>
<li> Appendix A. Stuff you (should) already know</li>
<li> Appendix B. System-specific gotchas</li>
<li> Appendix C. Zend Framework Core Components reference</li>
</ul>
<p><a href="http://www.manning.com/allen/meap_allench1.pdf"></a>雖然大部份章節還在撰寫當中，不過真的好想買來看喔~~尤其第二部份介紹的是一些很常用的功能，絕對值得 ZF 開發者買來參考。 </p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/4131729.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/4131729.html</guid>
	<category>Zend Framework</category>
	<pubDate>Thu, 13 Sep 2007 15:16:32 +0800</pubDate>
</item>
<item>
	<title>[PHP-ZF] Zend_Cache</title>
	<description><![CDATA[
	記一下剛剛看懂的 Zend_Cache 說明：

Frontend

指的是要快取的對象。

Backend

指的是儲存快取的容器。


然後 Zend_Cache 目前提供的 Frontend 及 Backend 相關資源如下： 

而 Core 是預設的 Frontend ，可以儲存大部份能被 serialize 的資源。
以下是官方提供建立 Cache 物件的方式：
&lt;?php
require 'Zend/Cache.php';
$backendName = 'File';
$frontendName = 'Core';
$frontendOptions = array([...]); // optional
$backendOptions = array([...]);  // optional
$cache = Zend_Cache::factory($frontendName, $backendName, $frontendOptions, $backendOptions);
以上的關係理解後，看官方手冊就更容易了。
註：不知道是年紀大而導致理解力衰退，還是 Zend_Cache 參數命名不直覺的關係？這麼簡單的東西想了好久...Orz

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>記一下剛剛看懂的 Zend_Cache 說明：</p>
<dl>
<dt><strong>Frontend</strong></dt>
<dd>
<p>指的是要快取的對象。</p>
</dd>
<dt><strong>Backend</strong></dt>
<dd>
<p>指的是儲存快取的容器。</p>
</dd>
</dl>
<p>然後 Zend_Cache 目前提供的 Frontend 及 Backend 相關資源如下： </p>
<p class="image"><img src="http://www.jaceju.net/resources/zend_cache/zend_cache.gif" alt="Zend_Cache" width="400" height="300" /></p>
<p>而 Core 是預設的 Frontend ，可以儲存大部份能被 serialize 的資源。</p>
<p>以下是官方提供建立 Cache 物件的方式：</p>
<pre><code>&lt;?php
require 'Zend/Cache.php';
$backendName = 'File';
$frontendName = 'Core';
$frontendOptions = array([...]); // optional
$backendOptions = array([...]);  // optional
$cache = Zend_Cache::factory($frontendName, $backendName, $frontendOptions, $backendOptions);</code></pre>
<p>以上的關係理解後，看官方手冊就更容易了。</p>
<p class="note">註：不知道是年紀大而導致理解力衰退，還是 Zend_Cache 參數命名不直覺的關係？這麼簡單的東西想了好久...Orz</p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/3992065.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/3992065.html</guid>
	<category>Zend Framework</category>
	<pubDate>Thu, 23 Aug 2007 20:02:23 +0800</pubDate>
</item>
<item>
	<title>[PHP] ZF 和 SEO</title>
	<description><![CDATA[
	老實說，我不是很懂 SEO 。
之所以喜歡 Zend Framewrok 的 Url Router 倒也不是因為 SEO ，而是因為自己寫一個是件很麻煩的事情。不過以下幾個連結可以讓對 Zend 加 SEO 有興趣的朋友參考看看：

Search Engine Friendly Websites with the Zend Framework
Just Say No to SEO
ZF and SEO

不過這年頭為什麼對機器好比對人好重要呀？大概是人比較難搞的關係吧？

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>老實說，我不是很懂 SEO 。</p>
<p>之所以喜歡 <a href="http://framework.zend.com/">Zend Framewrok</a> 的 Url Router 倒也不是因為 SEO ，而是因為自己寫一個是件很麻煩的事情。不過以下幾個連結可以讓對 Zend 加 SEO 有興趣的朋友參考看看：</p>
<ul>
<li><a href="http://devzone.zend.com/article/949-Search-Engine-Friendly-Websites-with-the-Zend-Framework">Search Engine Friendly Websites with the Zend Framework</a></li>
<li><a href="http://blog.calevans.com/2007/07/29/just-say-no-to-seo/" rel="bookmark" title="Permanent Link: Just Say No to SEO">Just Say No to SEO</a></li>
<li><a href="http://www.wormus.com/aaron/stories/2007/08/16/zf-and-seo.html" rel="bookmark" title="Permanent Link: ZF and SEO">ZF and SEO</a></li>
</ul>
<p>不過這年頭為什麼對機器好比對人好重要呀？大概是人比較難搞的關係吧？</p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/3939873.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/3939873.html</guid>
	<category>Zend Framework</category>
	<pubDate>Thu, 16 Aug 2007 13:43:11 +0800</pubDate>
</item>
<item>
	<title>[PHP-ZF] ZF 相關評論</title>
	<description><![CDATA[
	今天看到對岸兩位網友對 Zend Framework 有趣的評論，收錄如下：

Thinking In LAMP::我眼中的ZF
Some reminiscences, some memories::小议 Zend Framework 的三宗罪

基本上，我個人比較偏向 mikespook 的說法。
事實上 ZF 的確也是有不足的地方，但我想它目前也沒有要以官方自居；也許廖兄和王兄大概是認為大家都是以 ZF 是 Zend 官方的框架而盲目地推崇它，但是事實上就不是這樣呀！有開發經驗的又不是只有他們而已，在 ZF 的使用者中並不缺少高手呀！這些高手也看得出 ZF 的缺點所在，並進一步去解決這些問題或是分享他們的經驗，這才是技術人所應該做的事！
我想 ZF 本身還在成長當中，另外它還不斷在學習其他流行的框架上一些有用的技術 (看看那些提案) ，所以它進步的空間還很大。未來的發展還很難斷言，除非 ZF 開發團隊放棄，不然我本身其實還是對 ZF 抱有期待 (何況我都已經有專案用它上線了) 。 
註：先前我有提到專案還不適合用 ZF 的說詞，那是因為 ZF 那時還在 beta 階段，更動的可能性很大；而 ZF 1.0 出來後，大部份的功能也就底定了，當然可以用在專案上。
另外我個人也很欣賞 ZF 的程式碼標準，雖然它不一定是最漂亮的。當然每個人在程式碼格式上喜好不一定相同，不過在團隊中有一個共同的標準能夠遵守就是一件好事 (就像 RoR 的慣例一樣) 。
所以每個團隊有每個團隊自己喜好的開發方式，很多東西就不用太過武斷去評論它好或不好。就如 Mark 告訴我的，大家都能習慣且運用自如的話就是一個好框架。
註：剛剛看了一下， ZF 的首頁已經改版了，看起來還滿漂亮的。 

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>今天看到對岸兩位網友對 <a href="http://framework.zend.com">Zend Framework</a> 有趣的評論，收錄如下：</p>
<ul>
<li><a href="http://hi.baidu.com/thinkinginlamp">Thinking In LAMP</a>::<a href="http://hi.baidu.com/thinkinginlamp/blog/item/6282d539d96198f13a87ced1.html">我眼中的ZF</a></li>
<li><a href="http://blog.xxiyy.com/">Some reminiscences, some memories</a>::<a href="http://blog.xxiyy.com/index.php/archives/42">小议 Zend Framework 的三宗罪</a></li>
</ul>
<p>基本上，我個人比較偏向 mikespook 的說法。</p>
<p>事實上 ZF 的確也是有不足的地方，但我想它目前也沒有要以官方自居；也許廖兄和王兄大概是認為大家都是以 ZF 是 Zend 官方的框架而盲目地推崇它，但是事實上就不是這樣呀！有開發經驗的又不是只有他們而已，在 ZF 的使用者中並不缺少高手呀！這些高手也看得出 ZF 的缺點所在，並進一步去解決這些問題或是分享他們的經驗，這才是技術人所應該做的事！</p>
<p>我想 ZF 本身還在成長當中，另外它還不斷在學習其他流行的框架上一些有用的技術 (看看那些<a href="http://framework.zend.com/wiki/display/ZFPROP/Home">提案</a>) ，所以它進步的空間還很大。未來的發展還很難斷言，除非 ZF 開發團隊放棄，不然我本身其實還是對 ZF 抱有期待 (何況我都已經有專案用它上線了) 。 </p>
<p class="note">註：先前我有提到專案還不適合用 ZF 的說詞，那是因為 ZF 那時還在 beta 階段，更動的可能性很大；而 ZF 1.0 出來後，大部份的功能也就底定了，當然可以用在專案上。</p>
<p>另外我個人也很欣賞 ZF 的<a href="http://framework.zend.com/manual/en/coding-standard.html">程式碼標準</a>，雖然它不一定是最漂亮的。當然每個人在程式碼格式上喜好不一定相同，不過在團隊中有一個共同的標準能夠遵守就是一件好事 (就像 RoR 的慣例一樣) 。</p>
<p>所以每個團隊有每個團隊自己喜好的開發方式，很多東西就不用太過武斷去評論它好或不好。就如 Mark 告訴我的，大家都能習慣且運用自如的話就是一個好框架。</p>
<p class="note">註：剛剛看了一下， ZF 的首頁已經改版了，看起來還滿漂亮的。 </p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/3898093.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/3898093.html</guid>
	<category>Zend Framework</category>
	<pubDate>Thu, 09 Aug 2007 23:12:39 +0800</pubDate>
</item>
<item>
	<title>[PHP-ZF] 編譯 Zend Framework CHM 檔案</title>
	<description><![CDATA[
	以後要自己編譯最新的 Zend Framework CHM 格式的參考手冊了，這裡記一下完整的步驟。
步驟


安裝 cygwin 主程式，並加入套件 autoconf, automake, make, libxml2, libxml2-devel, libxslt ；安裝路徑我改為 d:\cygwin 。
註：勾選這些套件時，會把相依的套件也一起裝進來。如果沒有的話，可以把在 setup.exe 同一資料夾下的快取資料夾刪除，重新安裝即可。


下載 HTML Help Workshop ，並安裝它。


執行 cygwin ，以初始化 cygwin 環境，然後輸入 exit 離開。這時候 d:\cygwin\home 會多出一個資料夾，名稱即為你目前登入 Windows 的使用者名稱，這裡我假設為 username 。


在 d:\cygwin\home\username 下執行：
svn co http://framework.zend.com/svn/framework/trunk/documentation/manual/en
當然也可以用 TortoiseSVN 來取出。


下載 http://framework.zend.com/docbook/xml/4.5/ 底下所有檔案，把它們存在 d:\cygwin\home\username\docbook\xml\4.5 底下。


到 http://sourceforge.net/projects/docbook/ 下載 docbook-xsl-1.7x.0.tar.gz ，把它存在 d:\cygwin\home\username\ 底下並解開，然後檢查 d:\cygwin\home\username\docbook-xsl-1.7x.0\htmlhelp\htmlhelp.xsl 存不存在。

修改 d:\cygwin\home\username\en\Makefile.in ，找到以下部份：
DOCBOOK_DTD=http://framework.zend.com/docbook/xml/4.5/docbookx.dtd
DOCBOOK_XSL=http://framework.zend.com/docbook-xsl/html/chunk.xsl
改成：
DOCBOOK_DTD=/home/username/docbook/xml/4.5/docbookx.dtd
DOCBOOK_XSL=/home/username/docbook-xsl-1.73.0/htmlhelp/htmlhelp.xsl
此步驟很重要，這會影響是不是能產生 toc.hhc 及 htmlhelp.hhp 這兩個檔案。


 再執行一次 cygwin ，這時候家目錄就是在 /home/username 底下。進入 en 資料夾開始編譯：
$ cd en
$ autoconf
$ ./configure
$ make
這樣就會在 d:\cygwin\home\username\en\html\ 底下產生所有 chm 會用到的檔案。


用 PSPad 的多重取代功能，把 d:\cygwin\home\username\en\html\ 底下的 html 檔裡面的 UTF-8 的空白字元代換成 ASCII 的空白字元，以免在 chm 搜尋時會看到亂碼。 (感謝 Mark 協助)
註：新的 SVN 裡已經不用再做此步驟。


下載修改過的樣式表及官方少附的小圖示，將它解壓到 d:\cygwin\home\username\en\html\ 資料夾下覆蓋過去即可。


開啟 d:\cygwin\home\username\en\html\htmlhelp.hhp ，編譯成 chm 。完成後在同一資料夾就會產生 htmlhelp.chm ，這個就是我們要的檔案了。


參考


如何正确的编译 Zend Framework 手册的 chm 版本


Windows下搭建Docbook环境



	]]>
	</description>
	<content:encoded><![CDATA[
	<p>以後要自己編譯最新的 Zend Framework CHM 格式的參考手冊了，這裡記一下完整的步驟。</p>
<h2>步驟</h2>
<ol>
<li>
<p>安裝 <a href="http://www.cygwin.com/">cygwin</a> 主程式，並加入套件 autoconf, automake, make, libxml2, libxml2-devel, libxslt ；安裝路徑我改為 d:\cygwin 。</p>
<p class="note">註：勾選這些套件時，會把相依的套件也一起裝進來。如果沒有的話，可以把在 setup.exe 同一資料夾下的快取資料夾刪除，重新安裝即可。</p>
</li>
<li>
<p>下載 <a href="http://www.microsoft.com/downloads/info.aspx?na=22&amp;p=1&amp;SrcDisplayLang=en&amp;SrcCategoryId=&amp;SrcFamilyId=&amp;u=/downloads/details.aspx?FamilyID=00535334-c8a6-452f-9aa0-d597d16580cc&amp;DisplayLang=en">HTML Help Workshop</a> ，並安裝它。</p>
</li>
<li>
<p>執行 cygwin ，以初始化 cygwin 環境，然後輸入 exit 離開。這時候 d:\cygwin\home 會多出一個資料夾，名稱即為你目前登入 Windows 的使用者名稱，這裡我假設為 username 。</p>
</li>
<li>
<p>在 d:\cygwin\home\username 下執行：</p>
<pre><code>svn co http://framework.zend.com/svn/framework/trunk/documentation/manual/en</code></pre>
<p>當然也可以用 <a href="http://tortoisesvn.tigris.org/">TortoiseSVN</a> 來取出。</p>
</li>
<li>
<p>下載 <a href="http://framework.zend.com/docbook/xml/4.5/">http://framework.zend.com/docbook/xml/4.5/</a> 底下所有檔案，把它們存在 d:\cygwin\home\username\docbook\xml\4.5 底下。</p>
</li>
<li>
<p>到 <a href="http://sourceforge.net/projects/docbook/">http://sourceforge.net/projects/docbook/</a> 下載 docbook-xsl-1.7x.0.tar.gz ，把它存在 d:\cygwin\home\username\ 底下並解開，然後檢查 d:\cygwin\home\username\docbook-xsl-1.7x.0\htmlhelp\htmlhelp.xsl 存不存在。</p>
</li>
<li><p>修改 d:\cygwin\home\username\en\Makefile.in ，找到以下部份：</p>
<pre><code>DOCBOOK_DTD=<strong>http://framework.zend.com/docbook/xml/4.5/docbookx.dtd</strong>
DOCBOOK_XSL=<strong>http://framework.zend.com/docbook-xsl/html/chunk.xsl</strong></code></pre>
<p>改成：</p>
<pre><code>DOCBOOK_DTD=<strong>/home/username/docbook/xml/4.5/docbookx.dtd</strong>
DOCBOOK_XSL=<strong>/home/username/docbook-xsl-1.73.0/htmlhelp/htmlhelp.xsl</strong></code></pre>
<p>此步驟很重要，這會影響是不是能產生 toc.hhc 及 htmlhelp.hhp 這兩個檔案。</p>
</li>
<li>
<p> 再執行一次 cygwin ，這時候家目錄就是在 /home/username 底下。進入 en 資料夾開始編譯：</p>
<pre><code>$ cd en
$ autoconf
$ ./configure
$ make</code></pre>
<p>這樣就會在 d:\cygwin\home\username\en\html\ 底下產生所有 chm 會用到的檔案。</p>
</li>
<li>
<p>用 PSPad 的多重取代功能，把 d:\cygwin\home\username\en\html\ 底下的 html 檔裡面的 UTF-8 的空白字元代換成 ASCII 的空白字元，以免在 chm 搜尋時會看到亂碼。 (感謝 Mark 協助)</p>
<p class="note">註：新的 SVN 裡已經不用再做此步驟。</p>
</li>
<li>
<p>下載修改過的<a href="http://www.jaceju.net/resources/zf_manual/zf_manual_style.zip">樣式表及官方少附的小圖示</a>，將它解壓到 d:\cygwin\home\username\en\html\ 資料夾下覆蓋過去即可。</p>
</li>
<li>
<p>開啟 d:\cygwin\home\username\en\html\htmlhelp.hhp ，編譯成 chm 。完成後在同一資料夾就會產生 htmlhelp.chm ，這個就是我們要的檔案了。</p>
</li>
</ol>
<h2>參考</h2>
<ul>
<li>
<p><a href="http://blog.xxiyy.com/index.php/archives/24" rel="bookmark">如何正确的编译 Zend Framework 手册的 chm 版本</a></p>
</li>
<li>
<p><a href="http://www.phpeye.com/article/view/id/55">Windows下搭建Docbook环境</a></p>
</li>
</ul>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/3878731.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/3878731.html</guid>
	<category>Zend Framework</category>
	<pubDate>Tue, 07 Aug 2007 14:23:39 +0800</pubDate>
</item>
<item>
	<title>[PHP-ZF] Zend Framework 釋出 1.0.1 版</title>
	<description><![CDATA[
	Zend Framework 釋出 1.0.1 版了，修正了 33 個 issues 。看起來跟我目前開發的專案沒有什麼大衝突，先跑幾天試試看，沒問題的話再更新。
另外昨天有個網友問了一些有關 ZF 的問題，讓我有個很深的感觸。
我不禁要問：不熟 PHP 能學好 ZF 嗎？ 
雖然一樣是寫程式，觀念其實也都差不多，但是每種語言的開發環境畢竟還是有所不同。總不能說為什麼 XXX 語言可以這樣做，為什麼 PHP 不行？再者 ZF 是基於 PHP5 開發的，所以 PHP5 的特性以及包含了哪些 library 最好也要搞清楚。而且不論是學習 .NET 或是 Java ，不都是熟悉該語言的基礎後才有辦法去運用它們的框架嗎？ 
牢騷就發到這裡了...睡覺去...

	]]>
	</description>
	<content:encoded><![CDATA[
	<p><a href="http://devzone.zend.com/article/2389-Zend-Framework-1.0.1-Releases">Zend Framework 釋出 1.0.1 版了</a>，修正了 33 個 <a href="http://framework.zend.com/changelog">issues</a> 。看起來跟我目前開發的專案沒有什麼大衝突，先跑幾天試試看，沒問題的話再更新。</p>
<p>另外昨天有個網友問了一些有關 ZF 的問題，讓我有個很深的感觸。</p>
<p>我不禁要問：不熟 PHP 能學好 ZF 嗎？ </p>
<p>雖然一樣是寫程式，觀念其實也都差不多，但是每種語言的開發環境畢竟還是有所不同。總不能說為什麼 XXX 語言可以這樣做，為什麼 PHP 不行？再者 ZF 是基於 PHP5 開發的，所以 PHP5 的特性以及包含了哪些 library 最好也要搞清楚。而且不論是學習 .NET 或是 Java ，不都是熟悉該語言的基礎後才有辦法去運用它們的框架嗎？ </p>
<p>牢騷就發到這裡了...睡覺去...</p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/3844631.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/3844631.html</guid>
	<category>Zend Framework</category>
	<pubDate>Wed, 01 Aug 2007 01:23:57 +0800</pubDate>
</item>
<item>
	<title>[PHP-ZF] 測試 ZF 的 MVC 架構</title>
	<description><![CDATA[
	Zend Framework 的 MVC 架構怎麼做單元測試呢？高手 Alex 來告訴你：
Automatic testing of MVC applications created with Zend Framework
註：這篇是今年三月的文章，所以實作的時候 ZF 及 PHPUnit 可能要依照目前的版本做一些調整。


	]]>
	</description>
	<content:encoded><![CDATA[
	<p>Zend Framework 的 MVC 架構怎麼做單元測試呢？高手 Alex 來告訴你：</p>
<p><a href="http://www.alexatnet.com/node/12">Automatic testing of MVC applications created with Zend Framework</a></p>
<p class="note">註：這篇是今年三月的文章，所以實作的時候 ZF 及 PHPUnit 可能要依照目前的版本做一些調整。</p>

		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/3720837.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/3720837.html</guid>
	<category>Zend Framework</category>
	<pubDate>Thu, 26 Jul 2007 15:33:37 +0800</pubDate>
</item>
<item>
	<title>Zend Framework 手冊 CHM 版</title>
	<description><![CDATA[
	一直以來覺得 Zend Framework 沒有 CHM 格式的手冊很不方便，沒想到對岸的朋友 mikespook 已經做好了。
請參考：编译了 CHM 的 Zend Framework 手册
至於如果有新的版本出來時要更新怎麼辦？也很簡單，照以下步驟自行製作即可：
註：詳細過程我就不多做說明了，各位聰明的朋友應該能夠自己舉一反三。


下載 Html Help Workshop 並安裝。


用 Html Help Workshop 解開 (Decompile) mikespook 製作的 zf-en-mikespook.chm 。 


這時候在解開的目錄裡會有一個 toc.hhc ，這個就是我們要的目錄結構了。


重新用 Html Help Workshop 建立一個新專案 (假設檔名為 zhchm.hhp ) ，把 toc.hhc 載入。


把英文版的 Zend Framework 官方 HTML 手冊下載回來解開，假設我們解到了 C:\Temp\zfmanual 下。 


把剛剛的 zfchm.hhp 和 toc.hhc 複製到  C:\Temp\zfmanual\documentation\manual\core\en 。


最後以 Html Help Workshop 開啟 zfchm.hhp 並編譯之，這樣就會在同一個目錄下得到 zfchm.chm 。


大功告成，特此感謝 mikespook 。 

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>一直以來覺得 Zend Framework 沒有 CHM 格式的手冊很不方便，沒想到對岸的朋友 <a href="http://blog.xxiyy.com/">mikespook</a> 已經做好了。</p>
請參考：<a href="http://blog.xxiyy.com/?p=7" target="_blank">编译了 CHM 的 Zend Framework 手册</a>
<p>至於如果有新的版本出來時要更新怎麼辦？也很簡單，照以下步驟自行製作即可：</p>
<p class="note">註：詳細過程我就不多做說明了，各位聰明的朋友應該能夠自己舉一反三。</p>
<ol>
<li>
<p>下載 <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=00535334-c8a6-452f-9aa0-d597d16580cc&amp;displaylang=en">Html Help Workshop</a> 並安裝。</p>
</li>
<li>
<p>用 Html Help Workshop 解開 (Decompile) mikespook 製作的 zf-en-mikespook.chm 。 </p>
</li>
<li>
<p>這時候在解開的目錄裡會有一個 toc.hhc ，這個就是我們要的目錄結構了。</p>
</li>
<li>
<p>重新用 Html Help Workshop 建立一個新專案 (假設檔名為 zhchm.hhp ) ，把 toc.hhc 載入。</p>
</li>
<li>
<p>把英文版的 Zend Framework 官方 HTML 手冊下載回來解開，假設我們解到了 C:\Temp\zfmanual 下。 </p>
</li>
<li>
<p>把剛剛的 zfchm.hhp 和 toc.hhc 複製到  C:\Temp\zfmanual\documentation\manual\core\en 。</p>
</li>
<li>
<p>最後以 Html Help Workshop 開啟 zfchm.hhp 並編譯之，這樣就會在同一個目錄下得到 zfchm.chm 。</p>
</li>
</ol>
<p>大功告成，特此感謝 mikespook 。 </p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/3591325.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/3591325.html</guid>
	<category>Zend Framework</category>
	<pubDate>Thu, 05 Jul 2007 10:37:22 +0800</pubDate>
</item>
<item>
	<title>Zend Framework 釋出 1.0.0 正式版</title>
	<description><![CDATA[
	就在昨天， Zend Framework 釋出了 1.0.0 正式版，主要修正了很多 RC 版發現的問題。 
請參考： Changelog 。 
我想這是 ZF 的一個重大里程碑，這也表示未來會有更多建構於 ZF 之上的網站或產品推出 (不過我想這只限國外) 。
至於我目前所開發的專案，也將會全部改用 ZF 1.0.0 正式版本來重新驗證。 
題外話，變形金剛真好看，強烈推薦。 :)

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>就在昨天， <a href="http://framework.zend.com/home">Zend Framework</a> 釋出了 1.0.0 正式版，主要修正了很多 RC 版發現的問題。 </p>
<p>請參考： <a href="http://framework.zend.com/changelog">Changelog</a> 。 </p>
<p>我想這是 ZF 的一個重大里程碑，這也表示未來會有更多建構於 ZF 之上的網站或產品推出 (不過我想這只限國外) 。</p>
<p>至於我目前所開發的專案，也將會全部改用 ZF 1.0.0 正式版本來重新驗證。 </p>
<p class="note">題外話，變形金剛真好看，強烈推薦。 :)</p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/3560761.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/3560761.html</guid>
	<category>Zend Framework</category>
	<pubDate>Sun, 01 Jul 2007 13:03:55 +0800</pubDate>
</item>
<item>
	<title>關於 Zend Framework 的一些想法</title>
	<description><![CDATA[
	我常在對岸的論壇看一些 PHP 開發者在討論 Zend Framework (以下簡稱 ZF) ，而 ZF 給他們的感覺像是另一個 PEAR ；而且他們認為雖然 ZF 有提供一個簡單的 MVC 框架，但是對於接觸過 CakePHP 或其他目前已經很成熟的框架的人來說， ZF 的 MVC 看起來像是小兒科。
對這樣的看法，我個人其實抱持著不同的意見。先前我本來也打算使用 CakePHP 來開發一個小專案，但是在接觸一陣子過後，我發現我實在無法瞭解 CakePHP 的原理架構。一來我發現我對 CakePHP 的神奇 MVC 架構一知半解 (就像 RoR 一樣) ，二來 CakePHP 的文件對資質愚眛的我來說實在是太難懂了。因此如果要像丫凱這樣的高手在短時間內瞭解 CakePHP ，對我來說很不容易。 
ZF 就不同了，沿習著 PHP 的傳統，它的文件一開始就非常豐富而且易懂；而且就算是英文程度不及中學生的我，也能很清楚瞭解文件裡所要表達的意義。加上範例簡單且容易整合，只要稍加修改，通常就能夠很快加入現有的專案裡。而且 ZF 在 MVC 外的類別庫包含了當下最有用的功能 (像是 Gdata 、 WebService 等) ，就算不使用 ZF 本身的 MVC ，這些類別庫也能為我們帶來高度的價值。
那麼比起其他框架， ZF 不足在哪裡呢？ 

	]]>
	</description>
	<content:encoded><![CDATA[
	<p>我常在對岸的論壇看一些 PHP 開發者在討論 <a href="http://framework.zend.com/">Zend Framework</a> (以下簡稱 ZF) ，而 ZF 給他們的感覺像是另一個 <a href="http://pear.php.net/">PEAR</a> ；而且他們認為雖然 ZF 有提供一個簡單的 MVC 框架，但是對於接觸過 <a href="http://www.cakephp.org/">CakePHP</a> 或其他目前已經很成熟的框架的人來說， ZF 的 MVC 看起來像是小兒科。</p>
<p>對這樣的看法，我個人其實抱持著不同的意見。先前我本來也打算使用 CakePHP 來開發一個小專案，但是在接觸一陣子過後，我發現我實在無法瞭解 CakePHP 的原理架構。一來我發現我對 CakePHP 的神奇 MVC 架構一知半解 (就像 <a href="http://www.rubyonrails.org/">RoR</a> 一樣) ，二來 CakePHP 的文件對資質愚眛的我來說實在是太難懂了。因此如果要像<a href="http://blog.darkhero.net/">丫凱</a>這樣的高手在短時間內瞭解 CakePHP ，對我來說很不容易。 </p>
<p>ZF 就不同了，沿習著 PHP 的傳統，它的文件一開始就非常豐富而且易懂；而且就算是英文程度不及中學生的我，也能很清楚瞭解文件裡所要表達的意義。加上範例簡單且容易整合，只要稍加修改，通常就能夠很快加入現有的專案裡。而且 ZF 在 MVC 外的類別庫包含了當下最有用的功能 (像是 Gdata 、 WebService 等) ，就算不使用 ZF 本身的 MVC ，這些類別庫也能為我們帶來高度的價值。</p>
<p>那麼比起其他框架， ZF 不足在哪裡呢？ </p>
		<a href="http://blog.roodo.com/jaceju/archives/3494131.html">(繼續閱讀...)</a>;
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/3494131.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/3494131.html</guid>
	<category>Zend Framework</category>
	<pubDate>Tue, 19 Jun 2007 13:11:48 +0800</pubDate>
</item>
<item>
	<title>Zend Framework 1.0.0 RC1 釋出</title>
	<description><![CDATA[
	Zend Framework 1.0.0 RC1 終於出來了，這次在 MVC 部份加入了 ViewRenderer 。
以下是主要的改動：

Zend_Controller has a new feature called the ViewRenderer, which makes it very easy to design controller actions. See docs for the new usage; there is a section in the Controller Migration section for updating your MVC applications.
Zend_Gdata has a new object-oriented usage, making this client very similar to the interface of Gdata clients for other programming languages. However, support for Google Calendar is unfinished and remains in the incubator.
Zend_Db statement classes now have a consistent interface and common classes and exceptions across all database adapters; however, binding query parameters and results to PHP variables by reference has a bug (logged as ZF-1440).
Zend_Filter_Input is a new class with an old name. This provides a solution for declaring rules to filter and validate groups of data, and it serves as a “cage” from which only values that pass your validation rules can be retrieved.
Zend_Service_StrikeIron is a new web service client in the incubator.

簡單介紹一下 ViewRenderer ：
ViewRender 主要是用來簡化 Action Cotroller 裡調用 View 的動作。舉例來說， 0.9.x 以前我們要在一個 action 裡顯示樣版會這麼做：
class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
        $this-&gt;initView();        // initialize view
        $this-&gt;view-&gt;baz = 'bat'; // set view variable
        $this-&gt;render();          // render view
    }
}
現在只需要：
class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
        $this-&gt;view-&gt;baz = 'bat'; // set view variable
    }
}
這樣就會自動做好初始化及呈現的動作，而舊程式幾乎也不用怎麼改。
如果有比較特別的情況不想用 ViewRenderer 的時候，就在 Front Controller 加上：
// Assuming $front is your front controller instance
$front-&gt;setParam('noViewRenderer', true);
詳細介紹可以參考： Zend Framework's MVC Introduces the ViewRenderer 。
註：不過我用的是整合 Smarty 的 View，這點引發的問題也許不大。

	]]>
	</description>
	<content:encoded><![CDATA[
	<p><a href="http://devzone.zend.com/node/view/id/2082">Zend Framework 1.0.0 RC1</a> 終於出來了，這次在 MVC 部份加入了 ViewRenderer 。</p>
<p>以下是主要的改動：</p>
<ul class="disc">
<li>Zend_Controller has a new feature called the ViewRenderer, which makes it very easy to design controller actions. See docs for the new usage; there is a section in the Controller Migration section for updating your MVC applications.</li>
<li>Zend_Gdata has a new object-oriented usage, making this client very similar to the interface of Gdata clients for other programming languages. However, support for Google Calendar is unfinished and remains in the incubator.</li>
<li>Zend_Db statement classes now have a consistent interface and common classes and exceptions across all database adapters; however, binding query parameters and results to PHP variables by reference has a bug (logged as ZF-1440).</li>
<li>Zend_Filter_Input is a new class with an old name. This provides a solution for declaring rules to filter and validate groups of data, and it serves as a “cage” from which only values that pass your validation rules can be retrieved.</li>
<li>Zend_Service_StrikeIron is a new web service client in the incubator.</li>
</ul>
<p>簡單介紹一下 ViewRenderer ：</p>
<p>ViewRender 主要是用來簡化 Action Cotroller 裡調用 View 的動作。舉例來說， 0.9.x 以前我們要在一個 action 裡顯示樣版會這麼做：</p>
<pre><code>class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
        $this-&gt;initView();        // initialize view
        $this-&gt;view-&gt;baz = 'bat'; // set view variable
        $this-&gt;render();          // render view
    }
}</code></pre>
<p>現在只需要：</p>
<pre><code>class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
        $this-&gt;view-&gt;baz = 'bat'; // set view variable
    }
}</code></pre>
<p>這樣就會自動做好初始化及呈現的動作，而舊程式幾乎也不用怎麼改。</p>
<p>如果有比較特別的情況不想用 ViewRenderer 的時候，就在 Front Controller 加上：</p>
<pre><code>// Assuming $front is your front controller instance
$front-&gt;setParam('noViewRenderer', true);</code></pre>
<p>詳細介紹可以參考： <a href="http://devzone.zend.com/node/view/id/2072">Zend Framework's MVC Introduces the ViewRenderer</a> 。</p>
<p class="note">註：不過我用的是<a href="http://akrabat.com/2006/12/23/extending-zend_view_interface-for-use-with-smarty/">整合 Smarty 的 View</a>，這點引發的問題也許不大。</p>
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/jaceju/archives/3368249.html</link>
	<guid>http://blog.roodo.com/jaceju/archives/3368249.html</guid>
	<category>Zend Framework</category>
	<pubDate>Tue, 29 May 2007 23:16:14 +0800</pubDate>
</item>
<item>
	<title>現在用 Zend Framework 適合嗎？</title>
	<description><![CDATA[
	Update: 本文寫作時間是 ZF 0.9x beta 版的時候，所以以下言論目前已經失效了。 :)
常有朋友跟我討論到一件事：那就是 Zend 官方的 Zend Framework ，適合用來開發新專案嗎？
我的想法是：目前來說絕對不適合！
為什麼呢？ Andries Seutens 的 Zend Framework - Zend.php rewritten 這篇文章說明了這點。
該文大意是， Zend.php 將會被拿掉，然後改以下三個類別來分擔它原來的工作：

    Zend_Loader (holds loadClass(), loadFile() etc.)
    Zend_Debug (holds dump())
    Zend_Version (holds VERSION constant and compareVersion())

換句話說， Zend Framework 在沒有正式宣告有穩定版本前，被改動的機會還是很大。 
當然 Zend Framewok 的開發團隊有他們的考量，這樣的考量好不好我沒辦法有什麼評斷。只是在不斷改版的過程裡，很多作法會被開發團隊遺棄或加入；很可能今天能用的程式，更新到 Zend Framework 的新版後就不能用了。所以我個人是認為 Zend Framework 還在調整階段，絕對不適合用在開發中的專案。
但是 Zend Framework 裡有非常多值得學習的 PHP5 用法，想要考認證的朋友不妨多去瞭解它。 

	]]>
	</descrip