溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Zend Framework之Loader以及PluginLoader怎么用

發(fā)布時(shí)間:2021-09-02 09:27:49 來(lái)源:億速云 閱讀:155 作者:小新 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹了Zend Framework之Loader以及PluginLoader怎么用,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

具體如下:

Zend Framework提供了Zend_Loader,用來(lái)動(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ù)字,連接符-,下劃線(xiàn)_及英文句號(hào).組成(半角)。$dirs參數(shù)則不限,可以使用中文等。

$dirs 參數(shù)用來(lái)指定文件所在目錄,可以是一個(gè)字符串或者數(shù)組。如果為 NULL,則程序?qū)?huì)到系統(tǒng)的 include_path 下尋找文件是否存在(include_path可在php.ini中設(shè)置--Haohappy注),如果是字符串或數(shù)組,則會(huì)到指定的目錄下去找,然后才是 include_path。

$once 參數(shù)為布爾類(lèi)型,如果為 TRUE,Zend_Loader::loadFile() 使用 PHP 函數(shù) » include_once() 加載文件,否則就是 PHP 函數(shù) » include()。(本參數(shù)只能是true或false,兩者區(qū)別就和include()和include_once()的區(qū)別一樣。)

2.加載類(lèi)

具體使用:

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 類(lèi)名將會(huì)根據(jù)下劃線(xiàn)(作為目錄分隔線(xiàn))對(duì)應(yīng)到相應(yīng)目錄下的PHP文件,并加上'.php',比如Container_Tree會(huì)指向Container\\Tree.php。
$dir     可以是數(shù)組或者字符串。目錄是除去類(lèi)名包含的目錄的路徑。

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è)類(lèi)的Autoloader功能已經(jīng)不推薦使用了,所以不再講述。還有其他的Autoloader,以后具體說(shuō)明。

5.插件加載器

幫助文章給出的具體實(shí)例如下,可參考使用:

很多 Zend Framework 組件支持插件,允許通過(guò)指定類(lèi)的前綴和到類(lèi)的文件(不需要在 include_path或不需要遵循傳統(tǒng)命名約定的文件)的路徑動(dòng)態(tài)加載函數(shù)。Zend_Loader_PluginLoader 提供了普通的函數(shù)來(lái)完成這個(gè)工作。

PluginLoader 的基本用法遵循 Zend Framework 的命名約定(一個(gè)文件一個(gè)類(lèi)),解析路徑時(shí),使用下劃線(xiàn)作為路徑分隔符。當(dāng)決定是否加載特別的插件類(lèi),允許傳遞可選的類(lèi)前綴來(lái)預(yù)處理。另外,路徑按 LIFO 順序來(lái)搜索。由于 LIFO 搜索和類(lèi)的前綴,允許命名空間給插件,這樣可以從早期注冊(cè)的路徑來(lái)覆蓋插件。

基本用例

首先,假定下面的目錄結(jié)構(gòu)和類(lèi)文件,并且根(toplevel)目錄和庫(kù)目錄在 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è)插件加載器來(lái)使各種各樣的視圖助手倉(cāng)庫(kù)可用:

<?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');
?>

接著用類(lèi)名中添加路徑時(shí)定義的前綴后面的部分來(lái)加載一個(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'
?>

類(lèi)加載后,就可以實(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í)例的情況下,也可選地允許共享插件,這是通過(guò)靜態(tài)注冊(cè)表來(lái)完成的,在實(shí)例化時(shí)需要注冊(cè)表名作為構(gòu)造器的第二個(gè)參數(shù):

<?php
// Store plugins in static registry 'foobar':
$loader = new Zend_Loader_PluginLoader(array(), 'foobar');
?>

其它使用同名注冊(cè)表來(lái)實(shí)例化 PluginLoader 的組件將可以訪(fǎng)問(wèn)已經(jīng)加載的路徑和插件。

處理插件路徑

上節(jié)的例子示例如何給插件加載器添加路徑,那么如何確定已經(jīng)加載的路徑或刪除他們呢?

如果沒(méi)有提供 $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)的特定的路徑。如果沒(méi)有提供 $path ,所有的和前綴相關(guān)的路徑被清除,如果提供了 $path 并且相應(yīng)的前綴存在,只有這個(gè)相關(guān)的路徑被清除。
測(cè)試插件和獲取類(lèi)的名字

有時(shí)候你想確定在執(zhí)行一個(gè)動(dòng)作之前是否插件類(lèi)已經(jīng)加載,isLoaded() 返回插件名的狀態(tài)。

PluginLoader 的另一個(gè)普通用例是確定已加載類(lèi)的完全合格的插件類(lèi)名,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。這里不在累述。

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Zend Framework之Loader以及PluginLoader怎么用”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI