中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在PHP中實現自動加載機制

發布時間:2021-06-08 15:43:27 來源:億速云 閱讀:271 作者:Leah 欄目:開發技術

今天就跟大家聊聊有關如何在PHP中實現自動加載機制,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

在傳統的應用中,通常自定義 __autoload()。如下

define("DIR", "/var/www/myWeb/myClass/");
function __autoload($classname) {
  require DIR.$classname.'.class.php';
}
$book = new Book();

上述代碼運作過程如下:

1. 自定義 __autoload 函數,它定義了類文件的加載方式
2. 當我們 new 一個 Book 實例時,它首先看當前是否包含了這個類,如果不存在則自動調用 __autoload 函數并將類名 Book 作為參數傳遞給這個函數。這實際上就是一種動態加載的方式,只有我們需要的類文件才會被加載。
3. 找到 __autoload 函數后,發現定義好的加載動作 require DIR.$classname.'.class.php'; 這時候它就會去 DIR 目錄下查找 Book.class.php 文件,如果存在這個文件則加載。
4. 關于類 Book.class.php 的定義必須滿足如下條件:類名和文件名一致;一個文件只定義一個類。

Book.class.php 文件如下

class Book {
  public function __construct() {
    echo "this is Book's construct\n";
  }
}
注冊多種加載模式

對于我們自己的簡單應用,一種加載模式可能夠用了,但是對于較大型的應用,上面的方式存在明顯的缺陷:__autoload函數不能重復定義,也就是說我們只能定義一種加載文件的模式,最終的結果就是我們的類只能放在一個地方,這顯然是不符合實際要求的。因此php使用了函數 spl_autoload_register 來代替 __autolaod

代碼如下:

define("MODEL_DIR", "/var/www/myWeb/myModel/");
define("CONTROLLER_DIR", "/var/www/myWeb/myController/");
// 定義Model類加載方式
function loadModel($classname) {
  $filename = MODEL_DIR.$classname.'.php';
  if (file_exists($filename))
    require $filename;
}
// 定義Controller加載方式
function loadController($classname) {
  $filename = CONTROLLER_DIR.$classname.'.php';
  if (file_exists($filename))
    require $filename;
}
// 注冊兩個加載函數
spl_autoload_register("loadModel");
spl_autoload_register("loadController");
// 自動加載類文件
$bookMode = new BookMode();
$bookController = new BookController();

在上面的代碼中,我們可以看到:

1. 可以使用任意函數名定義多個加載函數
2. 在 spl_autoload_register 對加載函數進行注冊,實際上應該是添加到一個類似雙向隊列的數據結構中。
3. 當我們 new 的對象不存在于當前文件時,它會自動從我們的加載函數中查找,并且是按照我們使用 spl_autoload_register 注冊的順序進行的。
4. 需要注意的是,此時如果我們定義了 __autoload 方法,也必須進行注冊,否則會被忽略。

spl_autoload_register三種注冊函數的方式:

spl_autoload_register(funName); // 直接注冊一個普通加載函數
spl_autoload_register(obj::method); // 注冊一個靜態加載方法
spl_autoload_regitser(array(obj, method)); // 當obj為類字符串時,只能加載靜態方法。否則都可以。

實例

在各種php框架中,也大量用到了自動加載機制,我們通過laravel的一個小例子來看下。

laravel通過 Ioc 容器幫我們管理依賴,讓我們可以通過函數參數的方式愉快地獲得了類實例,但我們也發現,我們并沒有require文件,那容器又是如何找到我們的文件地址的?下面我們就來解決這個問題。

通過入口文件 index.php 我們一步步搜索,可以找到 /vendor/composer/ClassLoader.php 文件。

部分代碼如下

public static function loadClassLoader($class)
{
  if ('Composer\Autoload\ClassLoader' === $class) {
    require __DIR__ . '/ClassLoader.php';
  }
}
public static function getLoader()
{
  if (null !== self::$loader) {
    return self::$loader;
  }
  spl_autoload_register(array('obj', 'loadClassLoader'), true, true);
  // 通過命名空間的方式使用注冊的加載類
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
  spl_autoload_unregister(array('obj', 'loadClassLoader'));
  if (PHP_VERSION_ID >= 50600) {
    // 該文件定義了包類和用戶類的命名空間和實體文件的映射
    // 以及其他一些東西
    require_once __DIR__ . '/autoload_static.php';
    // 初始化$loader一些屬性。
    // 我們關注autoload_static.php文件的類映射
    // 被賦值在了 $loader的$classMap屬性
        call_user_func(\Composer\Autoload\ComposerStaticInit::getInitializer($loader));
    // ...
  }
  // ...
  $loader->register(true);
  // ...
  return $loader;
}

它調用了 getLoader() 函數,并將 loadClassLoader 函數注冊到加載函數注冊隊列。然后就可以通過命名空間的方式 self::$loader = $loader = new \Composer\Autoload\ClassLoader(); 實例化 ClassLoader 類。

緊接著,他載入了 /autoload_static.php 文件,大致內容如下

// 里面還定義了包類和psr的一些標準
public static $classMap = array (
  'App\\Common\\Collection' => __DIR__ . '/../..' . '/app/Common/Collection.php',
  'App\\Common\\MgDB' => __DIR__ . '/../..' . '/app/Common/MgDB.php',
  'App\\Common\\Redis' => __DIR__ . '/../..' . '/app/Common/Redis.php',
)

看到這里筆者興奮了,因為上面的 Collection, Redis 正是筆者定義的類!
然后就是我們在laravel經常聽到的一個名詞 “register”。查看 ClassLoader 類的 register 方法如下:

public function register($prepend = false)
{
  spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
public function loadClass($class)
{
  if ($file = $this->findFile($class)) {
    includeFile($file);
    return true;
  }
}
public function findFile($class)
{
  // ...
  // class map lookup
  if (isset($this->classMap[$class])) {
    return $this->classMap[$class];
  }
  // ...
}

上面的register方法同樣使用了自動加載機制。并將通過findFile函數和$classMap數組直接找到對應的類的具體位置。這也就是我們不用自己去加載類文件的原因 – 當我們實例化一個代碼中找不到的類時,它便會在這里加載對應的類。

看到這里我們也發現了它的使用和我們之前講的并不完全一致,我們是注冊函數是為了通過文件夾來尋找類,而laravel注冊函數是為了注冊一個映射數組然后直接調用(整了個映射文件三千多行。。。)具體為什么要這么做得等下次通讀加載源碼部分后再寫一篇博文(本來只想找一個框架的例子,蜜汁尷尬)

筆者實例

兩年前負責學校某個協會線上部分時,主要是做微信開發,因為時不時就要加一個新功能,所以如果用一般的方式寫起來是比較痛苦的,但是用框架又有點大材小用。因為就使用了下面這種簡單的方式:

require "./basic/init.php";
define('WEB_PATH', '');
//聲明自動加載函數并注冊,指示加載路徑與加載方法
  function wechatAutoload($class_name)
  {
    $file_road = './function/'.$class_name.'.class.php';
    if(file_exists($file_road))
    {
      require_once($file_road);
    }
  }
  spl_autoload_register('wechatAutoload');
//----------------------------------------------

看完上述內容,你們對如何在PHP中實現自動加載機制有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

php
AI

长寿区| 保康县| 汤原县| 武功县| 乌拉特中旗| 怀柔区| 林周县| 新竹县| 若羌县| 德兴市| 五原县| 云梦县| 铁岭市| 乌什县| 汶川县| 探索| 安宁市| 廉江市| 左权县| 垦利县| 边坝县| 沁水县| 宜章县| 临沧市| 措美县| 建德市| 利辛县| 丹江口市| 肥城市| 施甸县| 怀宁县| 利津县| 新丰县| 浮山县| 白水县| 砚山县| 蕉岭县| 新巴尔虎右旗| 高邮市| 西藏| 嘉鱼县|