Zend Framework教程之Loader以及PluginLoader用法詳解
本文實(shí)例分析了Zend Framework中Loader以及PluginLoader用法。分享給大家供大家參考,具體如下:
Zend Framework提供了Zend_Loader,用來動(dòng)態(tài)加載文件。
以下是具體用法,以及具體實(shí)現(xiàn):
1.加載文件
使用方法:
Zend_Loader::loadFile($filename, $dirs=null, $once=false);
具體實(shí)現(xiàn):
/** * 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; }
參數(shù)規(guī)則:
正如實(shí)現(xiàn)方法,有如下參數(shù)
$filename參數(shù)指定需要加載的文件,注意$filename不需要指定任何路徑,只需要文件名即可。ZF會(huì)對(duì)文件作安全性檢查。$filename 只能由字母,數(shù)字,連接符-,下劃線_及英文句號(hào).組成(半角)。$dirs參數(shù)則不限,可以使用中文等。
$dirs 參數(shù)用來指定文件所在目錄,可以是一個(gè)字符串或者數(shù)組。如果為 NULL,則程序?qū)?huì)到系統(tǒng)的 include_path 下尋找文件是否存在(include_path可在php.ini中設(shè)置--Haohappy注),如果是字符串或數(shù)組,則會(huì)到指定的目錄下去找,然后才是 include_path。
$once 參數(shù)為布爾類型,如果為 TRUE,Zend_Loader::loadFile() 使用 PHP 函數(shù) » include_once() 加載文件,否則就是 PHP 函數(shù) » include()。(本參數(shù)只能是true或false,兩者區(qū)別就和include()和include_once()的區(qū)別一樣。)
2.加載類
具體使用:
Zend_Loader::loadClass('Container_Tree', array( '/home/production/mylib', '/home/production/myapp' ) );
具體實(shí)現(xiàn):
/** * 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 類名將會(huì)根據(jù)下劃線(作為目錄分隔線)對(duì)應(yīng)到相應(yīng)目錄下的PHP文件,并加上'.php',比如Container_Tree會(huì)指向Container\\Tree.php。
$dir 可以是數(shù)組或者字符串。目錄是除去類名包含的目錄的路徑。
3.判斷某個(gè)文件是否可讀
具體使用:
if (Zend_Loader::isReadable($filename)) { // do something with $filename }
具體實(shí)現(xiàn):
/** * 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; }
具體參數(shù):
$filename參數(shù)指定了要檢查的文件名,包括路徑信息。這個(gè)方法是將 PHP 函數(shù)» is_readable()封裝而成的,is_readable() 不會(huì)自動(dòng)查找 include_path 下的文件,而 Zend::isReadable() 可以。
4.Autoloader
這個(gè)類的Autoloader功能已經(jīng)不推薦使用了,所以不再講述。還有其他的Autoloader,以后具體說明。
5.插件加載器
幫助文章給出的具體實(shí)例如下,可參考使用:
很多 Zend Framework 組件支持插件,允許通過指定類的前綴和到類的文件(不需要在 include_path或不需要遵循傳統(tǒng)命名約定的文件)的路徑動(dòng)態(tài)加載函數(shù)。Zend_Loader_PluginLoader 提供了普通的函數(shù)來完成這個(gè)工作。
PluginLoader 的基本用法遵循 Zend Framework 的命名約定(一個(gè)文件一個(gè)類),解析路徑時(shí),使用下劃線作為路徑分隔符。當(dāng)決定是否加載特別的插件類,允許傳遞可選的類前綴來預(yù)處理。另外,路徑按 LIFO 順序來搜索。由于 LIFO 搜索和類的前綴,允許命名空間給插件,這樣可以從早期注冊(cè)的路徑來覆蓋插件。
基本用例
首先,假定下面的目錄結(jié)構(gòu)和類文件,并且根(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
現(xiàn)在,創(chuàng)建一個(gè)插件加載器來使各種各樣的視圖助手倉庫可用:
<?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'); ?>
接著用類名中添加路徑時(shí)定義的前綴后面的部分來加載一個(gè)給定的視圖助手:
<?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' ?>
類加載后,就可以實(shí)例化了。
Note: 為一個(gè)前綴注冊(cè)多個(gè)路徑
有時(shí)候,多個(gè)路徑使用相同的前綴,Zend_Loader_PluginLoader 實(shí)際上為每個(gè)給定的前綴注冊(cè)一個(gè)路徑數(shù)組;最后注冊(cè)的被首先檢查,當(dāng)你使用孵化器里的組件時(shí),這相當(dāng)有用。
Note: 實(shí)例化時(shí)定義路徑
你可以提供給構(gòu)造器一個(gè)可選的“前綴/路徑”對(duì)(或“前綴/多個(gè)路徑”)數(shù)組參數(shù):
<?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 在不需要使用單態(tài)實(shí)例的情況下,也可選地允許共享插件,這是通過靜態(tài)注冊(cè)表來完成的,在實(shí)例化時(shí)需要注冊(cè)表名作為構(gòu)造器的第二個(gè)參數(shù):
<?php // Store plugins in static registry 'foobar': $loader = new Zend_Loader_PluginLoader(array(), 'foobar'); ?>
其它使用同名注冊(cè)表來實(shí)例化 PluginLoader 的組件將可以訪問已經(jīng)加載的路徑和插件。
處理插件路徑
上節(jié)的例子示例如何給插件加載器添加路徑,那么如何確定已經(jīng)加載的路徑或刪除他們呢?
如果沒有提供 $prefix,getPaths($prefix = null) 以“前綴/路徑”對(duì)返回所有的路徑;或者如果提供了 $prefix,getPaths($prefix = null) 返回為給定的前綴注冊(cè)的路徑。
clearPaths($prefix = null) 將缺省地清除所有的已注冊(cè)路徑,或者如果提供了 $prefix 并放在堆棧里,只清除和那些和給定前綴關(guān)聯(lián)的路徑。
removePrefixPath($prefix, $path = null) 允許有選擇地清除和給定前綴相關(guān)的特定的路徑。如果沒有提供 $path ,所有的和前綴相關(guān)的路徑被清除,如果提供了 $path 并且相應(yīng)的前綴存在,只有這個(gè)相關(guān)的路徑被清除。
測試插件和獲取類的名字
有時(shí)候你想確定在執(zhí)行一個(gè)動(dòng)作之前是否插件類已經(jīng)加載,isLoaded() 返回插件名的狀態(tài)。
PluginLoader 的另一個(gè)普通用例是確定已加載類的完全合格的插件類名,getClassName() 提供該功能。一般地,這個(gè)和 isLoaded() 聯(lián)合使用:
<?php if ($loader->isLoaded('Adapter')) { $class = $loader->getClassName('Adapter'); $adapter = call_user_func(array($class, 'getInstance')); } ?>
具體插件加載器的實(shí)現(xiàn)可以參考Zend_Loader_PluginLoader和Zend_Loader。這里不在累述。
更多關(guān)于zend相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Zend FrameWork框架入門教程》、《php優(yōu)秀開發(fā)框架總結(jié)》、《Yii框架入門及常用技巧總結(jié)》、《ThinkPHP入門教程》、《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門教程》、《php+mysql數(shù)據(jù)庫操作入門教程》及《php常見數(shù)據(jù)庫操作技巧匯總》
希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。
- Zend Framework連接Mysql數(shù)據(jù)庫實(shí)例分析
- 解析如何使用Zend Framework 連接數(shù)據(jù)庫
- zend framework配置操作數(shù)據(jù)庫實(shí)例分析
- Zend Framework框架教程之Zend_Db_Table_Rowset用法實(shí)例分析
- Zend Framework教程之Zend_Db_Table_Row用法實(shí)例分析
- Zend Framework教程之Zend_Db_Table用法詳解
- Zend Framework入門知識(shí)點(diǎn)小結(jié)
- Zend Framework緩存Cache用法簡單實(shí)例
- Zend Framework基本頁面布局分析
- Zend Framework教程之配置文件application.ini解析
- Zend Framework教程之MVC框架的Controller用法分析
- Zend Framework教程之連接數(shù)據(jù)庫并執(zhí)行增刪查的方法(附demo源碼下載)
相關(guān)文章
laravel框架路由分組,中間件,命名空間,子域名,路由前綴實(shí)例分析
這篇文章主要介紹了laravel框架路由分組,中間件,命名空間,子域名,路由前綴,結(jié)合實(shí)例形式分析了laravel框架路由分組,中間件,命名空間,子域名,路由前綴相關(guān)概念、原理與基本使用方法,需要的朋友可以參考下2020-02-02Laravel框架中VerifyCsrfToken報(bào)錯(cuò)問題的解決
這篇文章主要給大家介紹了關(guān)于Laravel框架中VerifyCsrfToken報(bào)錯(cuò)問題的解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí),需要的朋友們下面跟著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-08-08php實(shí)現(xiàn)smarty模板無限極分類的方法
這篇文章主要介紹了php實(shí)現(xiàn)smarty模板無限極分類的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了php使用smarty模板實(shí)現(xiàn)數(shù)據(jù)庫查詢與無限極分類的相關(guān)技巧,需要的朋友可以參考下2015-12-12PHP 自動(dòng)加載的簡單實(shí)現(xiàn)(推薦)
下面小編就為大家?guī)硪黄狿HP 自動(dòng)加載的簡單實(shí)現(xiàn)(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-08-08Aliyun Linux 編譯安裝 php7.3 tengine2.3.2 mysql8.0 redis5的過程詳解
這篇文章主要介紹了Aliyun Linux 編譯安裝 php7.3 tengine2.3.2 mysql8.0 redis5,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10