2021年3月13日 星期六

PHP 的自動載入功能

設定目標:
  • 了解 PHP 如何自動載入需要的模組程式

模組自動載入
  1. PHP 原有的模組載入方式
    • include : 載入其他的 php 程式檔!當執行錯誤時,不會停止程式運作!
    • include_once : 相同的檔案,只會載入一次!
    • require : 載入其他的 php 程式檔!當執行錯誤時,會停止程式運作!
    • reuqire_once : 相同的檔案,只會載入一次!
  2. 缺點 : 若需要載入大量檔案程式,程式碼將會十分難看與難以除錯與管理!
  3. PHP 自動導入模組方式
    • 當須要用到該使用的物件時,才去真正的引入該類別
    • __autoload 用法 :
      • 例 : 有一個目錄 Classes ,裡面有個 Member.php 的檔案,Classes 目錄外面有兩個檔案 autoload.php 以及 index.php
        +Classes
        +--Member.php
        -autoload.php
        -index.php
        
      • Member.php 檔案內容:
        <?php
        //這是 Classes/Member.php
        class Member{
          public function getMemberList(){
            echo "print member list...
        "; } } ?>
      • autoload.php 檔案內容:
        <?php
        function __autoload($className){
          $filename = __DIR__ . "/classes/" . $className . ".php";
          if (is_readable($filename)){
            require $filename;
          }
        }
        ?>
        
      • index.php 檔案內容:
        <?php
        //這是 index.php
        include_once __DIR__ . "/autoload.php";
        
        $member = new Member();
        $member->getMemberList();
        ?>
        ?>
        
      • 缺點 : __autoload() 不能重覆的被定義!
  4. 使用 SPL(Standard PHP Library)
    • spl_autoload:
      • 預設實作 __autoload() magic function
      • 當 spl_autoload_register() 沒有定義或是沒有帶任何參數的時候,預設會採用 __autoload() 這個 function
    • spl_autoload_register
      • 能夠註冊自行定義的 autoload function
      • 當 spl_autoload_register() 有註冊之後,__autoload() 將會失效,必需自己手動將 __autoload() 註冊,才能使用。
    • 例 : 在原來的範例目錄內,增加 first 以及 second 這兩個目錄以及 First.php 與 Second.php 兩個檔案!另外再新增兩個 firstAutoload.php 以及 secondAutoload.php 檔案!
      +Classes
      +--Member.php
      +first
      +--First.php
      +second
      +--Second.php
      -firstAutoload.php
      -secondAutoload.php
      -autoload.php
      -index.php
      
    • First.php 檔案內容:
      <?php
      //這是 first/First.php
      class First{
        public function doSomething(){
          echo "I am first class...
      "; } } ?>
    •     
    • Second.php 檔案內容:
      <?php
      //這是 second/Second.php
      class Second{
        public function doSomething(){
          echo "I am second class...
      "; } } ?>
    •     
    • firstAutoload.php 檔案內容:
      <?php
      //這是 firstAutoload.php
      function firstAutoload($className){
        $filename = __DIR__ . "/first/" . $className . ".php";
        if (is_readable($filename)){
          require $filename;
        }
      }
      //向 spl_autoload 註冊這個方法的名稱
      spl_autoload_register('firstAutoload');
      ?>
      
    •     
    • secondAutoload.php 檔案內容:
      <?php
      //這是 secondAutoload.php
      function secondAutoload($className){
        $filename = __DIR__ . "/second/" . $className . ".php";
        if (is_readable($filename)){
          require $filename;
        }
      }
      //向 spl_autoload 註冊這個方法的名稱
      spl_autoload_register('secondAutoload');
      ?>
      
    • 修改 index.php 檔案內容:
      <?php
      //修改後的 index.php
      include_once __DIR__ . "/firstAutoload.php";
      include_once __DIR__ . "/secondAutoload.php";
      
      $first = new First();
      $first->doSomething();
      
      $second = new Second();
      $second->doSomething();
      ?>
      
    • 缺點 : 每新增一個目錄,就需要寫一個 autoload 檔案!不好管理!
    • 改進方式 : 寫一個 allAutoload.php,再使用 array、foreach 導入!
      <?php
      //這是 allAutoload.php
      function allAutoload($className){
      $folders = array(__DIR__ . "/first/",
                       __DIR__ ."/second/",
                       );
      
      foreach ($folders as $folder){
          $fileName = $folder . $className . ".php";
          if (is_readable($fileName)){
             require $fileName;
          }
        }
      }
      
      //註冊
      spl_autoload_register('allAutoload');
      ?>
      
    • 再次修改 index.php 檔案內容:
      <?php
      //又修改了 index.php
      include_once __DIR__ . "/allAutoload.php";
      $first = new First();
      $first->doSomething();
      
      $second = new Second();
      $second->doSomething();
      ?>
      
    • 缺點 : 每次新增一個 class 目錄,就要異動一次 autoload 檔案!

本章練習:
  • 修改你的 dog 、cat 以及 human 的所有類別,讓他們可以自動導入到執程式中!