在 WebMVC 中, View 的部份通常是由兩個部份組成的:樣版引擎及樣版;而 Zend Framework 也是以此基礎來實作,而且功能更加強大而複雜。
以下我們分四個部份來初步認識 Zend Framework 的 View 層。
Zend_View 的基礎
在 Zend Framework 裡,樣版引擎的部份就是由 Zend_View 擔當,基本的樣版引擎功能都可以在 Zend_View 見到。
Zend_View 是可以單獨使用的,用法也相當簡單。假設我們有個 view_test.php 內容如下:
1 2 3 4 5 6 7 8 9 10 11 12 | |
程式一開始除了建立要輸出的 $data 資料外,我們還建立了一個 Zend_View 物件。但其他的程式又分別代表什麼意思呢?以下我們來一一解釋。
Base Path
1
| |
與大部份樣版引擎相同,我們要先指定 Zend_View 所能讀取的樣版路徑。但我們要先解釋一下 Zend_View 在樣版路徑上的一個設計,請先參考下圖:
1 2 3 4 | |
基本上 Zend_View 需要一個 Base Path 用來放置 filters 、 helpers 及 scripts 等三個目錄,這三個目錄的名稱是固定的。而 scripts 就是用來放置樣版的目錄,其他兩個目錄則較少用到,有機會會再為大家介紹。
一個 Zend_View 物件可以同時擁有多個 Base Paths ,因此在讀取樣版時, Zend_View 會逐一在這些 Base Paths 中尋找樣版。
設定 Base Path 的方法是 setBasePath() 或 addBasePath() 這兩個方法,一般用途下這兩者並沒有差異。唯一的差異在於 setBasePath() 方法會先清空原先已經設定的 Base Path 組合後,再新增一組新的 Base Path ;而 addBasePath() 方法則是再新增另一組 Base Path 。
另外透過 addScriptPath() 方法也可以讓我們直接指定 Script Path ,這時 Zend_View 就不受限於 scripts 這個名稱的影響了,例如:
1
| |
指定樣版變數
1
| |
然後我們可以用設定屬性值的方式,將資料指定成 View 物件的樣版變數 (因為用了 __set() 這個魔術方法) ;或是我們也可以改用 assign() 方法:
1
| |
不論是指定物件屬性或是呼叫 assign() 方法,都是一樣的效果。
輸出內容
1
| |
最後我們可以透過 render() 方法來得到最終的結果,再用 echo 來輸出它。這裡 render() 方法中的樣版並不需要給它完整路徑,只要指定相對於 Script Path 的路徑即可。因此這行程式的意思就是找到相對於 view_test.php 的 scripts/booklist.php ,然後在處理完後顯示結果。
另外要注意的是,獨立運作時的 Zend_View ,其樣版的副檔名是沒有限制的。不過在 Zend Framework 預設 MVC 架構下,副檔名預設會是 phtml ,稍後我們再解釋為什麼。
樣版內容
Zend_View 在樣版的部份一般就是指 HTML ,不過通常我們也可改用其他格式的樣版,例如 XML 。 Zend Framework 將樣版稱為 View Scripts ,基本的語法就是 PHP 本身。
所以上面的 booklist.php 就是我們的 View Script ,其內容如下:
1 2 3 4 5 6 | |
對 View Script 來說,這裡的 $this 就是我們在 view_test.php 裡所建立的 View 物件;其他敘述的用法也都跟一般寫 PHP 沒什麼兩樣,但建議使用 PHP 的 Alternative syntax for control structures ,會讓 View Script 較為容易理解與維護。
另外很重要的是,當我們在輸出變數的值時,一定要記得用 Zend_View 內建的 escape() 方法來避免被 XSS 攻擊,這是一般初學者最常忽略的地方。
當然 View Script 還可以使用更多方便的功能,之後會再對這些功能做較為深入的介紹。
專案架構中的 View Script
在 Zend Framework 預設的專案架構中使用 View Script 前,我們要先知道 View Script 的位置是怎麼安排的。
在預設的專案結構裡, Zend_View 的 Base Path 路徑設定即為 application/views 。參考前面的說明,可以知道預設的 View Script 就會被安排在 application/views/scripts 這個目錄下。
在 scripts 這個目錄下又會再區分出多個子目錄,每個子目錄其實就是對應一個 Action Controller 。例如 application/views/scripts/index 目錄就是對應 IndexController 這個 Action Controller 類別;同理,如果是 BlogController 這個類別,那邊它就會對應到 application/views/scripts/blog 。
而子目錄就是存放 View Script 的地方,預設每個 View Script 都對應到一個 Action Controller 的 action 方法。例如 application/views/scripts/index/index.phtml 就是對應 IndexController 類別中的 indexAction 方法;同理 IndexController 類別的 articleAction() 方法就會對應到 application/views/scripts/index/article.phtml 這個 View Script 。
不過一個 action 還可以對應到好幾個不同格式的 View Script ,這點在另一篇「初探 Zend Framework 上的 Context 輸出」有說明,這裡不再詳述。
Controller 與 View 的溝通方式
預設在 Action Controller 中已經預先建立好一個 Zend_View 物件並做好初始化了,我們可以直接使用。
註:當然除了預設的 Zend_View 之外,我們也可以改用第三方的樣版引擎;例如 Smarty 等知名的樣版引擎,其整合可以參考「 Smarty 2 整合到 Zend Framework 1.10 的重點整理」一文。
我們可以在 Action Controller 裡使用 $this->view 這個屬性,來直接存取已經初始化好的 Zend_View 物件;例如最上面的例子,我們在 IndexController 類別裡的 indexAction() 中就可以直接這麼寫:
1 2 3 4 5 6 7 8 9 10 | |
當然別忘了把 application/views/scripts/index/index.phtml 改成:
1 2 3 4 5 6 | |
然後瀏覽專案首頁,就可以看到跟上例一模一樣的效果。
這裡最酷的地方在於 Action Controller 不需要呼叫 View 物件的 render() 方法來輸出樣版,這件事完全由 Zend Framework 的 MVC 框架自動處理掉了;而在自動處理的過程中, Zend Framework 也會幫我們找出 Action 對應的 View Script 路徑,並以預設的 phtml 為副檔名。因此我們只要專心在怎麼去取得資料,並將資料放到 View 物件裡,其他的事全部會由 Zend Framework 幫我們完成。
註:自動完成的原理,之後有機會再詳述。
基本的 View Helper
有如 Smarty 的 Plugin 一般, Zend_View 也支援所謂的 View Helper 。 View Helper 主要是協助我們快速地對樣版上的元素做處理,以下介紹兩個剛開始就會用到的 View Helper 。
BaseUrl
在 Portable ZF 專案中,我們常需要知道目前專案根目錄相對於網站根目錄的路徑,以便取得 CSS 、 JavaScript 或 Image 等公開資源相對於網站根目錄的路徑。這個路徑一般稱為 Base Url ;假設現在我們的 ZF 專案首頁網址為:
1
| |
那麼 Base Url 就是 /portable 。
而 BaseUrl 這個 View Helper 就是協助我們取得 Base Url 資訊的好幫手,在 View Script 裡面的我們只需要用:
1
| |
就可以取得 Base Url 了。而 BaseUrl 也接受一個相對路徑的參數,例如:
1
| |
就會得到 /portable/css/style.css 。
Url
這個 View Helper 會協助我們處理內連網址,例如以 portable 這個專案來說,在 View Script 中如果呼叫了 Url 這個 View Helper :
1 2 3 4 | |
這樣就會輸出 /portable/index/user 這個相對網址。
各位一定會好奇,那為什麼不直接使用 Base Url 加上 /index/user 就好了呢?原因是為了能讓 View Script 輸出反向編譯後的 Route 網址。假設我們在 application.ini 中有設定以下的 Route :
1 2 3 | |
那麼我們可以直接在網址列輸入:
1
| |
這樣的網址會讓程式連到 IndexController 的 userAction() 去執行。反過來如果我們希望在 View Script 中產生這樣的網址,如果不使用 url 的話就是這樣寫:
1
| |
這樣有個缺點,那就是如果 Route 的規則修改了的話,那麼有輸出這種網址的 View Script 全部都要改。但是如果改用 Url 這個 View Helper 的話,就可以避免掉這個問題:
1 2 3 | |
Url View Helper 的第一個參數是告訴 Url 要將 :username 替換成 jaceju 這個值,第二個參數則是告訴 Url 要使用 author 這個 Route 的反向編譯。這麼一來我們就算修改了 author 這個 Route 的規則,也不必再更動所有的 View Scripts 了。
註: Route 機制有機會的話,會再向大家作介紹。
小結
瞭解 Zend Framework 的 View 層是進入 Zend Framework 世界的基本功夫,學會它的基礎後,我們就可以很容易地處理資料所要呈現的方式。
本文介紹了 Zend_View 這個套件的基本用法,還有 Action Controller 是如何跟 View 互動的;另外也介紹了兩個最常用的 View Helper : BaseUrl 及 Url 。這些都是 Zend Framework 入門時需要先瞭解的知識。
當然 Zend_View 還有其他可以繼續深入研究的功能,往後有機會的話,我會再一一為大家介紹。