這篇文章主要介紹了Zend Framework教程之Loader以及PluginLoader用法,結合執行個體形式詳細分析了Zend Framework自動載入機制的原理,使用方法與相關注意事項,需要的朋友可以參考下
本文執行個體分析了Zend Framework中Loader以及PluginLoader用法。分享給大家供大家參考,具體如下:
Zend Framework提供了Zend_Loader,用來動態負載檔案。
以下是具體用法,以及具體實現:
1.負載檔案
使用方法:
Zend_Loader::loadFile($filename, $dirs=null, $once=false);
具體實現:
/** * Loads a PHP file. This is a wrapper for PHP's include() function. * * $filename must be the complete filename, including any * extension such as ".php". Note that a security check is performed that * does not permit extended characters in the filename. This method is * intended for loading Zend Framework files. * * If $dirs is a string or an array, it will search the directories * in the order supplied, and attempt to load the first matching file. * * If the file was not found in the $dirs, or if no $dirs were specified, * it will attempt to load it from PHP's include_path. * * If $once is TRUE, it will use include_once() instead of include(). * * @param string $filename * @param string|array $dirs - OPTIONAL either a path or array of paths * to search. * @param boolean $once * @return boolean * @throws Zend_Exception */public static function loadFile($filename, $dirs = null, $once = false){ self::_securityCheck($filename); /** * Search in provided directories, as well as include_path */ $incPath = false; if (!empty($dirs) && (is_array($dirs) || is_string($dirs))) { if (is_array($dirs)) { $dirs = implode(PATH_SEPARATOR, $dirs); } $incPath = get_include_path(); set_include_path($dirs . PATH_SEPARATOR . $incPath); } /** * Try finding for the plain filename in the include_path. */ if ($once) { include_once $filename; } else { include $filename; } /** * If searching in directories, reset include_path */ if ($incPath) { set_include_path($incPath); } return true;}
參數規則:
正如實現方法,有如下參數
$filename參數指定需要載入的檔案,注意$filename不需要指定任何路徑,只需要檔案名稱即可。ZF會對檔案作安全性檢查。$filename 只能由字母,數字,串連符-,底線_及英文句號.組成(半形)。$dirs參數則不限,可以使用中文等。
$dirs 參數用來指定檔案所在目錄,可以是一個字串或者數組。如果為 NULL,則程式將會到系統的 include_path 下尋找檔案是否存在(include_path可在php.ini中設定--Haohappy注),如果是字串或數組,則會到指定的目錄下去找,然後才是 include_path。
$once 參數為布爾類型,如果為 TRUE,Zend_Loader::loadFile() 使用 PHP 函數 » include_once() 負載檔案,否則就是 PHP 函數 » include()。(本參數只能是true或false,兩者區別就和include()和include_once()的區別一樣。)
2.載入類
具體使用:
Zend_Loader::loadClass('Container_Tree', array( '/home/production/mylib', '/home/production/myapp' ));
具體實現:
/*** Loads a class from a PHP file. The filename must be formatted* as "$class.php".** If $dirs is a string or an array, it will search the directories* in the order supplied, and attempt to load the first matching file.** If $dirs is null, it will split the class name at underscores to* generate a path hierarchy (e.g., "Zend_Example_Class" will map* to "Zend/Example/Class.php").** If the file was not found in the $dirs, or if no $dirs were specified,* it will attempt to load it from PHP's include_path.** @param string $class - The full class name of a Zend component.* @param string|array $dirs - OPTIONAL Either a path or an array of paths* to search.* @return void* @throws Zend_Exception*/public static function loadClass($class, $dirs = null){ if (class_exists($class, false) || interface_exists($class, false)) { return; } if ((null !== $dirs) && !is_string($dirs) && !is_array($dirs)) { require_once 'Zend/Exception.php'; throw new Zend_Exception('Directory argument must be a string or an array'); } // Autodiscover the path from the class name // Implementation is PHP namespace-aware, and based on // Framework Interop Group reference implementation: // http://groups.google.com/group/php-standards/web/psr-0-final-proposal $className = ltrim($class, '\\'); $file = ''; $namespace = ''; if ($lastNsPos = strripos($className, '\\')) { $namespace = substr($className, 0, $lastNsPos); $className = substr($className, $lastNsPos + 1); $file = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR; } $file .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; if (!empty($dirs)) { // use the autodiscovered path $dirPath = dirname($file); if (is_string($dirs)) { $dirs = explode(PATH_SEPARATOR, $dirs); } foreach ($dirs as $key => $dir) { if ($dir == '.') { $dirs[$key] = $dirPath; } else { $dir = rtrim($dir, '\\/'); $dirs[$key] = $dir . DIRECTORY_SEPARATOR . $dirPath; } } $file = basename($file); self::loadFile($file, $dirs, true); } else { self::loadFile($file, null, true); } if (!class_exists($class, false) && !interface_exists($class, false)) { require_once 'Zend/Exception.php'; throw new Zend_Exception("File \"$file\" does not exist or class \"$class\" was not found in the file"); }}
$class 類名將會根據底線(作為目錄分隔線)對應到相應目錄下的PHP檔案,並加上'.php',比如Container_Tree會指向Container\\Tree.php。
$dir 可以是數組或者字串。目錄是除去類名包含的目錄的路徑。
3.判斷某個檔案是否可讀
具體使用:
if (Zend_Loader::isReadable($filename)) { // do something with $filename}
具體實現:
/** * Returns TRUE if the $filename is readable, or FALSE otherwise. * This function uses the PHP include_path, where PHP's is_readable() * does not. * * Note from ZF-2900: * If you use custom error handler, please check whether return value * from error_reporting() is zero or not. * At mark of fopen() can not suppress warning if the handler is used. * * @param string $filename * @return boolean */public static function isReadable($filename){ if (is_readable($filename)) { // Return early if the filename is readable without needing the // include_path return true; } if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && preg_match('/^[a-z]:/i', $filename) ) { // If on windows, and path provided is clearly an absolute path, // return false immediately return false; } foreach (self::explodeIncludePath() as $path) { if ($path == '.') { if (is_readable($filename)) { return true; } continue; } $file = $path . '/' . $filename; if (is_readable($file)) { return true; } } return false;}
具體參數:
$filename參數指定了要檢查的檔案名稱,包括路徑資訊。這個方法是將 PHP 函數» is_readable()封裝而成的,is_readable() 不會自動尋找 include_path 下的檔案,而 Zend::isReadable() 可以。
4.Autoloader
這個類的Autoloader功能已經不推薦使用了,所以不再講述。還有其他的Autoloader,以後具體說明。
5.外掛程式載入器
協助文章給出的具體執行個體如下,可參考使用:
很多 Zend Framework 組件支援外掛程式,允許通過指定類的首碼和到類的檔案(不需要在 include_path或不需要遵循傳統命名規範的檔案)的路徑動態載入函數。Zend_Loader_PluginLoader 提供了普通的函數來完成這個工作。
PluginLoader 的基本用法遵循 Zend Framework 的命名規範(一個檔案一個類),解析路徑時,使用底線作為路徑分隔字元。當決定是否載入特別的外掛程式類,允許傳遞可選的類首碼來預先處理。另外,路徑按 LIFO 順序來搜尋。由於 LIFO 搜尋和類的首碼,允許命名空間給外掛程式,這樣可以從早期註冊的路徑來覆蓋外掛程式。
基本用例
首先,假定下面的目錄結構和類檔案,並且根(toplevel)目錄和庫目錄在 include_path 中:
application/
modules/
foo/
views/
helpers/
FormLabel.php
FormSubmit.php
bar/
views/
helpers/
FormSubmit.php
library/
Zend/
View/
Helper/
FormLabel.php
FormSubmit.php
FormText.php
現在,建立一個外掛程式載入器來使各種各樣的視圖助手倉庫可用:
<?php$loader = new Zend_Loader_PluginLoader();$loader->addPrefixPath('Zend_View_Helper', 'Zend/View/Helper/') ->addPrefixPath('Foo_View_Helper', 'application/modules/foo/views/helpers') ->addPrefixPath('Bar_View_Helper', 'application/modules/bar/views/helpers');?>
接著用類名中添加路徑時定義的首碼後面的部分來載入一個給定的視圖助手:
<?php// load 'FormText' helper:$formTextClass = $loader->load('FormText'); // 'Zend_View_Helper_FormText';// load 'FormLabel' helper:$formLabelClass = $loader->load('FormLabel'); // 'Foo_View_Helper_FormLabel'// load 'FormSubmit' helper:$formSubmitClass = $loader->load('FormSubmit'); // 'Bar_View_Helper_FormSubmit'?>
類載入後,就可以執行個體化了。
Note: 為一個首碼註冊多個路徑
有時候,多個路徑使用相同的首碼,Zend_Loader_PluginLoader 實際上為每個給定的首碼註冊一個路徑數組;最後註冊的被首先檢查,當你使用孵化器裡的組件時,這相當有用。
Note: 執行個體化時定義路徑
你可以提供給構造器一個可選的“首碼/路徑”對(或“首碼/多個路徑”)數組參數:
<?php$loader = new Zend_Loader_PluginLoader(array( 'Zend_View_Helper' => 'Zend/View/Helper/', 'Foo_View_Helper' => 'application/modules/foo/views/helpers', 'Bar_View_Helper' => 'application/modules/bar/views/helpers'));?>
Zend_Loader_PluginLoader 在不需要使用單態執行個體的情況下,也可選地允許共用外掛程式,這是通過靜態註冊表來完成的,在執行個體化時需要註冊表名作為構造器的第二個參數:
<?php// Store plugins in static registry 'foobar':$loader = new Zend_Loader_PluginLoader(array(), 'foobar');?>
其它使用同名註冊表來執行個體化 PluginLoader 的組件將可以訪問已經載入的路徑和外掛程式。
處理外掛程式路徑
上節的例子樣本如何給外掛程式載入器添加路徑,那麼如何確定已經載入的路徑或刪除他們呢?
如果沒有提供 $prefix,getPaths($prefix = null) 以“首碼/路徑”對返回所有的路徑;或者如果提供了 $prefix,getPaths($prefix = null) 返回為給定的首碼註冊的路徑。
clearPaths($prefix = null) 將預設地清除所有的登入路徑,或者如果提供了 $prefix 並放在堆棧裡,只清除和那些和給定首碼關聯的路徑。
removePrefixPath($prefix, $path = null) 允許有選擇地清除和給定首碼相關的特定的路徑。如果沒有提供 $path ,所有的和首碼相關的路徑被清除,如果提供了 $path 並且相應的首碼存在,只有這個相關的路徑被清除。
測試外掛程式和擷取類的名字
有時候你想確定在執行一個動作之前是否外掛程式類已經載入,isLoaded() 返回外掛程式名的狀態。
PluginLoader 的另一個普通用例是確定已載入類的完全合格的外掛程式類名,getClassName() 提供該功能。一般地,這個和 isLoaded() 聯合使用:
<?phpif ($loader->isLoaded('Adapter')) { $class = $loader->getClassName('Adapter'); $adapter = call_user_func(array($class, 'getInstance'));}?>
具體外掛程式載入器的實現可以參考Zend_Loader_PluginLoader和Zend_Loader。這裡不在累述。
以上就是本文的全部內容,希望對大家的學習有所協助,更多相關內容請關注topic.alibabacloud.com!