PHP 手冊 (類與物件) 學習筆記四:類的自動載入

小彭友發表於2020-06-01

場景:在編寫物件導向(OOP) 程式時,很多開發者為每個類新建一個 PHP 檔案。 這會帶來一個煩惱:每個指令碼的開頭,都需要包含(include)一個長長的列表(每個類都有個檔案)。

在 PHP 5 中,已經不再需要這樣了。 spl_autoload_register() 函式可以註冊任意數量的自動載入器,當使用尚未被定義的類(class)和介面(interface)時自動去載入。通過註冊自動載入器,指令碼引擎在 PHP 出錯失敗前有了最後一個機會載入所需的類。
Tip: 儘管 __autoload() 函式也能自動載入類和介面,但更建議使用 spl_autoload_register() 函式。 spl_autoload_register() 提供了一種更加靈活的方式來實現類的自動載入(同一個應用中,可以支援任意數量的載入器,比如第三方庫中的)。因此,不再建議使用 __autoload() 函式,在以後的版本中它可能被棄用。

Note:

  • 在 PHP 5.3 之前,__autoload 函式丟擲的異常不能被 catch 語句塊捕獲並會導致一個致命錯誤(Fatal Error)。 自 PHP 5.3 起,能夠 thrown 自定義的異常(Exception),隨後自定義異常類即可使用。 __autoload 函式可以遞迴的自動載入自定義異常類。

  • 自動載入不可用於 PHP 的 CLI 互動模式

  • 如果類名比如被用於 call_user_func()則它可能包含一些危險的字元,比如 ../。 建議您在這樣的函式中不要使用使用者的輸入,起碼需要在 __autoload() 時驗證下輸入。
    Example 1:自動載入示例

    spl_autoload_register(function ($classname){
          require_once $classname.'.php';
      });
      $o1 = new MyClass1();//myclass1
      $o2 = new MyClass2();//myclass2
    
      class MyClass1
      {
          public function __construct()
          {
              echo "myclass1";
          }
      }
    
      class MyClass2
      {
            public function __construct()
           {  
              echo "myclass2";
           }
       }

    Example 2:嘗試載入介面ITest

     spl_autoload_register(function ($name){
          var_dump($name);
      });
    
      class Foo implements ITest{
    
      }
      /*
          string(5) "ITest"
          Fatal error: Interface 'ITest' not found in ...
        */

    Examle 3:自動載入在 PHP 5.3.0+ 中的異常處理

    spl_autoload_register(function ($name){
          echo "want to load {$name}.\n";
          throw new Exception("unable to load $name.");
      });
    
      try{
          $obj = new MyClass1();
      } catch (Exception $e){
          echo $e->getMessage(), "\n";
      }
      /*
          Want to load MyClass1.
          Unable to load MyClass1.
       */

    Example 4:自動載入在 PHP 5.3.0+ 中的異常處理 - 沒有自定義異常機制

      spl_autoload_register(function ($name){
          echo "want to load {$name}.\n";
          throw new MissingException("unable to load $name.");
      });
    
      try{
          $obj = new MyClass1();
      } catch (Exception $e){
          echo $e->getMessage(), "\n";
      }
      /*
          Want to load MyClass1.
          Want to load MissingException.
          Fatal error: Class 'MissingException' not found in testMissingException.php on line 4
       */

    Exmaple 5:筆記中值的學習的自動載入

    class Autoloader
    {
      public static function register()
      {
          spl_autoload_register(function ($class) {
              $file = str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
              if (file_exists($file)) {
                  require_once $file;
                  return true;
              }
              return false;
          });
      }
    }
    Autoloader::register();
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章