最近因為工作需要用到ZF,所以就來摸一下
Zend Framework是php裡頭其中一種Framework,因為它實作的是按照MVC架構做的,所以要先把MVC的概念看懂,
可以參考維基寫的MVC
建立目錄架構:
首先把網站目錄結構建成(目錄結構規劃不一定要參照這個方式):
另外設個DNS指到Project/public這個目錄
下載Zend Framework:
接著下載Zend Framework
他有 Full 跟 minimal 兩個版本,建議是下載Full,下載下來後解壓縮並把 /(Zend_Framework)/library/Zend整個目錄複製到你的Project/library下
建立index:
我們先在Project/public底下建立一個index.php,這支index.php的用途就是把除了靜態檔案以外,把其他的request都交給Zend Framework來處理,所以記得要把Rewrite的功能開起來。
首先在Project/public底下建一個.htaccess,填入以下內容:
2 | RewriteCond %{REQUEST_FILENAME} -s [OR] |
3 | RewriteCond %{REQUEST_FILENAME} -l [OR] |
4 | RewriteCond %{REQUEST_FILENAME} -d |
5 | RewriteRule ^.*$ - [NC,L] |
6 | RewriteRule ^.*$ index.php [NC,L] |
這段Rewrite的設定就是將所有目錄、檔案以外的URL都交給index.php處理,比如http://localhost/img/a.png便會直接吐內容,如果是http://localhost/foo/bar這類的就會丟給index.php處理
RewriteCond指令定義了規則生效的條件,也就是說RewriteCond要符合才會跑RewriteRule
-s:測試路徑名稱是否存在
-l:測試路徑名稱並確認是否有一個存在的符號連接
-d:測試路徑目錄是否存在
接著要設定index.php的內容:
3 | define( 'APPLICATION_PATH' , realpath (dirname( __FILE__ ) . '/../application/' )); |
5 | define( 'APPLICATION_ENVIRONMENT' , 'development' ); |
8 | date_default_timezone_set( 'Asia/Taipei' ); |
11 | set_include_path(APPLICATION_PATH . '/../library' . PATH_SEPARATOR . get_include_path()); |
14 | require_once 'Zend/Loader/Autoloader.php' ; |
16 | $autoloader = Zend_Loader_Autoloader::getInstance(); |
19 | $autoloader ->setFallbackAutoloader(true); |
22 | $frontController = Zend_Controller_Front::getInstance(); |
24 | $frontController ->setControllerDirectory(APPLICATION_PATH . '/controllers' ); |
26 | $frontController ->setParam( 'env' , APPLICATION_ENVIRONMENT); |
28 | $frontController ->dispatch(); |
Action Controller:
先在Project/application/controllers裡面建一個IndexController.php,在Zend Framework裡可以將request都交由front controller下的dispatcher來決定要交由哪個action controller來處理,所以controller命名的方式就是URL名稱(開頭大寫)Controller.php。例如http://DNS/foo就會去執行FooController的indexAction;http://DNS/foo/bar就是執行FooController的barAction。如果將Action命名成testOneAction,則DNS會對應成test-one
接著在IndexController.php輸入以下內容:
2 | class IndexController extends Zend_Controller_Action { |
3 | public function init() { |
6 | public function indexAction() { |
8 | $this ->_helper->viewRenderer->setNoRender(); |
9 | echo 'hello from Index#index' ; |
這時只要輸入http://DNS/就可以看到畫面顯示出hello from Index#index的字串
View Script:
剛剛上述Action的作法,只是拿來測試controller是否正常執行,事實上是不符合MVC架構的,controller是拿來運算而非拿來顯示的,顯示的部份必須由view來執行!
在Zend Framework中,action controller預設都會有一個view renderer來負責顯示的工作,他會根據controller/action的名稱去找application/views/scripts/controller_name/action.phtml來顯示,例如剛剛上述的IndexController/indexAction就會去找index/index.phtml,所以先在application/views/scripts底下建一個index目錄,index的目錄裡再建一個index.phtml
再將Project/application/controllers/IndexController.php改成以下內容:
2 | class IndexController extends Zend_Controller_Action { |
3 | public function init() { |
6 | public function indexAction() { |
8 | $this ->view->today = date ( 'Y-m-d' ); |
接著輸入Project/application/views/scripts/index/index.phtml內容:
3 | < h1 >It's <? php echo $this->today; ?> today.</ h1 > |
這樣http://DNS/就會顯示出日期了
URL Routing:
上面有提過Controller和Action的命名方式,現在來實作一下 http://DNS/foo 和 http://DNS/foo/bar
首先先在Project/application/controllers裡建一個FooController.php並輸入以下內容:
2 | class FooController extends Zend_Controller_Action { |
3 | public function indexAction() { |
5 | $this ->_helper->viewRenderer->setNoRender(); |
8 | public function barAction(){ |
10 | $this ->_helper->viewRenderer->setNoRender(); |
選擇View Scripts:
上述有提到view renderer來負責顯示的工作,他會根據controller/action的名稱去找符合的phtml檔,
例如上述提到的狀況,若是改成view輸出,則應該會在Project/application/views/scripts/foo/裡多出index.phtml和bar.phtml
但Action也可以直接選擇其他的view script來顯示。
例如將Project/application/controllers裡的FooController.php改成:
2 | class FooController extends Zend_Controller_Action { |
3 | public function indexAction() { |
4 | $this ->view->msg = "Foo#index" ; |
8 | public function barAction(){ |
10 | $this ->view->msg = "Foo#bar" ; |
Project/application/views/scripts/foo/bar.phtml:
2 | It's <? php echo $this->msg; ?>. |
使用Layout排版:
在設計網站時,都會有一些固定的版型,比如Header或sidebar大家都長一樣,只是內容不同而已,這樣的需求可以用Zend Framework中的Layout元件來完成。
首先要使用Layout元件時,需要一開始初始化時就把元件打開,並且設定layout存放的路徑,所以必須在Project/index.php中再加入一段程式碼:
5 | Zend_Layout::startMvc( array ( 'layoutPath' => APPLICATION_PATH . '/views/layouts' )); |
接著在Project/application/views/layouts/layout.phtml
8 | < div id = "hd" >< h1 >Header</ h1 ></ div > |
10 | < div id = "bd" ><? php echo $this->layout()->content; ?></ div > |
11 | < div id = "ft" >< small >Footer</ small ></ div > |
現在可以試試上述幾個已經完成測試的foo/bar就都有layout了
選擇不同的Layout:
跟view script一樣,Layout也是可以選擇的,當然你要在Project/application/views/layouts裡再建一個,比如建了一個test_layout.phtml,
只要在Controller.php裡的Action方法加上以下這段程式碼就可以了:
1 | $this ->_helper->layout->setLayout( 'test_layout' ); |
關閉Layout:
如果開啟了Layout元件,但某些action不需要用到Layout,
一樣在Controller.php裡的Action方法加上以下這段程式碼就可以了:
1 | $this ->_helper->layout->disableLayout(); |
錯誤處理:
當寫程式時,發生問題是難免的事,Zend Framework吐出來的錯誤訊息有點亂,可以做個簡單的錯誤處理畫面,
先在Project/application/controllers/裡建一個ErrorController.php
在ErrorController.php:
2 | class ErrorController extends Zend_Controller_Action { |
3 | public function errorAction() { |
5 | $error = $this ->_getParam( 'error_handler' ); |
7 | $response = $this ->getResponse(); |
10 | $this ->_helper->viewRenderer->setNoRender(); |
12 | $this ->_helper->layout->disableLayout(); |
13 | switch ( $error ->type) { |
15 | case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER: |
17 | case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION: |
19 | $response ->setHttpResponseCode(404); |
20 | echo "<h1>Page Not Found</h1>" ; |
23 | $response ->setHttpResponseCode(500); |
24 | echo "<h1>Application Error</h1>" ; |
此時當網頁有錯誤時,便會執行ErrorController的errorAction