網站製作學習誌

記錄學習製作網站的一切

初探 Zend Framework 如何自動載入類別

剛接觸 Zend Framework 的朋友,大概會覺得它的架構非常複雜,光是要用 require/include 來載入一個類別就要寫好長的路徑。所幸 Zend Framework 提供了一套自動載入類別的機制,幫助我們直接在程式裡使用類別,而不需要事先引入它們的宣告。

但是自動載入類別機制本身卻令人頭大,因為它常常會以非常理的方式去自動找到我們所要的類別,入門的朋友大概在這邊就會陣亡或選擇投降了吧。

因此本文就先為大家介紹 Zend Framework 自動載入機制的原理,以下我們一一來看吧。

Autoloader

Zend Framework 在自動載入類別的機制,基本上是由 Zend_Loader_Autoloader 來實現,其目的主要是管理其他類別載入器。不過 Zend_Loader_Autoloader 的原理較為複雜,有機會我再撰文介紹。

這邊我們先不談如何使用 Zend_Loader_Autoloader 類別,而是要告訴大家在不寫任何程式的狀況下 (但需要寫一些設定) , Zend Framework 如何載入類別的。

一般類別的載入

基本上 Zend Framework 會遵循 PEAR 命名法來載入類別,也就是 Zend/Xxx/Yyy.php 這個檔案對應到 Zend_Xxx_Yyy 這個類別;這些類別的找尋方式是先從 library 目錄開始找起,找不到的話就再從 include_path 所設定的路徑去找;也就是在 index.php (入口) 中定義的這段程式碼:

1
2
3
4
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path(),
)));

所以通常在需要連 Zend Framework 或第三方套件一起帶著走的專案,就可以把它們放在 library 這個目錄裡;而如果有多個專案共用這些套件的話,就可以將它們放在 include_path 定義的路徑裡。

不過事情通常沒有那麼簡單。

因為在 Zend Framework 裡還有一個 namespace 的概念,使自動載入機制用起來會讓入門者有所困惑。像是除了在 index.php 我們必須將 Zend/Application.php 直接用 require_once 載入外,在專案裡我們都可以直接使用 Zend 套件,就是因為 Zend_ 是一個內定的 namespace 。

預設的 namespace 有 Zend 及 ZendX ,所以如果我們需要自己的 namespace 時,就必須向 Zend_Loader_Autoloader 註冊。

註冊方法很簡單,就是在 application.ini 裡加上:

1
Autoloadernamespaces[] = "My"

這個意思就是告訴 Zend_Loader_Autoloader 我們要向它註冊一個叫做 My 的 namespace ,當然 My 這個名稱是可以自訂的。

現在假設我們依照了 PEAR 的命名規則製作好 My 的套件,並將它們放在 library 下;而且有個類別叫做 My_Test ,它對應到了 library/My/Test.php 這個檔案;那麼我們要在 Action Controller 裡使用它時,就可以直接這樣寫:

1
$test = new My_Test();

這樣 Zend_Loader_Autoloader 就會自動幫我們把 library/My/Test.php 這個檔案載入了。

資源類別的載入

所謂的資源類別就是指 Model 、 Form 等這些 Zend Framework 中常用的類別;它們所在的路徑和它們的類別名稱並不是遵照 PEAR 的命名規則,這也使得入門者容易產生疑惑。

舉例來說, MVC 中我們常會用到的 model ,在 Zend Framework 裡預設是對應 application/models 這個路徑。假設我們用 zf 指令建立了一個名為 Test 的 model :

1
zf create model Test

它就會在 application/models 下建立一個 Test.php 的類別檔案,而其類別名稱為 Application_Model_Test ;換句話說,這個類別並不能依照上面所提到的一般類別的方式來找到其對應的檔案路徑。但是我們卻可以在 Action Controller 裡直接使用它:

1
$test = new Application_Model_Test();

奇怪吧?所以我們來把類別名稱分成三部份,也就是 Application 、 Model 和 Test ,再一一來瞭解它們跟路徑的關係。

首先 Application 是在 application.ini 中所定義的 appnamespace 的值,所以它跟路徑是無關的。如果我們改變了 appnamespace 這個值,那麼透過 zf 指令所建立出來的資源類別的類別名稱就會以這個值來置首。

註:不過在更改 appnamespace 前所建立的類別就不會同步修改了,我們必須手動調整。

而 Model 則是因為 Zend_Application_Module_Autoloader 已經幫我們定義好這些類別路徑的對應,它會直接對應到 models 這個路徑。而 models 這個路徑前面還必須要再加上一個 Base Path ,預設就是 /path/to/project/application 。

預設在 Zend_Application_Module_Autoloader 中已經定義了以下幾個類別路徑:

資源名稱 對應路徑
Model_DbTable models/DbTable
Model_Mapper models/mappers
Form forms
Model models
Plugin plugins
Service services
View_Helper views/helpers
View_Filter views/filters

依照這個對應表,我們可以直接建立相關的目錄及類別來使用,而不需要再煩惱類別載入的部份。

最後的 Test 這個名稱,就是跟 Test.php 這個檔案的主檔名對應;從這邊開始,我們就可以使用 PEAR 命名法來規劃類別名稱與路徑的對應,例如 Xxx_Yyy 對應到 Xxx/Yyy 這個路徑。

舉個例子,假設現在我們要建立一個 Application_Form_Admin_Login 這個表單類別。我們可以在 application/models 下再建立一個 Admin 目錄 (注意大小寫) ,然後在這個目錄下再建立一個 Login.php 檔案,其內容為:

1
2
3
4
5
6
7
8
<?php
class Application_Form_Admin_Login extends Zend_Form
{
    public function init()
    {
        /* Form Elements & Other Definitions Here ... */
    }
}

這樣就可以在 Action Controller 裡直接建立 Application_Form_Admin_Login 物件來使用了。

當然我們也可以用 zf 指令幫我們建立,但是 zf 指令在 create form 時,是不能使用底線做為 form 的名稱的;因此我們可以先用 zf 指令建立一個 Login 表單類別,再將它移到 Admin 目錄裡,最後再將類別改名為 Application_Form_Admin_Login 。

其他資源也是依照同樣的方式來被自動載入,因此我們就不必大費周章地找出它們的絕對路徑了。

註:類似 zf create form/model name module 雖然也可以幫我們在模組下建立 Form 或 Model ,但它們並不是依照上述的方式來對應路徑,無法在不寫程式的狀況下把它們載入。

特例

像是 Action Controller 類別 (像是 application/controllers 下的 IndexController 類別) 就不是透過 Autoloader 載入的,它們的載入是由 Zend_Controller_Dispatcher_Standard 類別所控制,與 Autoloader 無關。

小結

本文介紹了在專案剛建立好後,幾種類別的載入方式;這些機制都是 Zend Framework 所提供最基本的類別載入方法,在開發 Zend Framework 專案時一定要好好掌握它們。

之後有機會的話,還會為大家介紹其他 Autoloader 的載入機制,它們將更強大更複雜。

謝謝收看。

Comments