2021年3月14日 星期日

PHP 的命名空間

設定目標:
  • 了解 PHP 如何定義命名空間,改善自動載入的缺點!

命名空間概念與實作
  1. 命名空間(Namespace)
    • PSR 規範 : PHP-FIG 提出的規範,目的是讓 PHP 開發者在撰寫時有一個建議規範可遵循,使得開發者間可進行有效溝通與開發!
    • PSR-4 規範了一套 namespace 統一作法,包含了原有的 PSR-0 所規範的 autoload 作法!
    • 利用Composer 來進行 autoload 可提昇編輯效率!
    • PHP 檔案內的關鍵字 :
      • namespace : 定義類別的完整類別名稱
      • use : 導入需要使用的類別名稱
    • PSR-4 正確的命名空間,其完整的類別名稱語法如下 :
      \<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
      
      • 完整的類別名稱(fully qualified class name)必須有最高層級(top-level)的命名空間(namespace),通常稱這個命名空間為「供應商命名空間(vendor namespace)」。
      • 完整的類別名稱可以有一個或多個子命名空間。
      • 一個完整的類別名稱必須以類別名稱結束。
      • 在完整的類別名稱中,底線沒有其他意義。
      • 完整的類別名稱可以由英文字母大小寫組合而成。
      • 所有的類別名稱必須是有區分大小寫的。
    • 重點 :
      • 命名空間 + 類別名稱 = 路徑 + 檔名.php
      • 命名空間、類別,都需要開頭大寫
      • 底線不要拿來當作分類,例如 : Like_Book.php、Like_Movie.php,應該改成路徑 Like/Book.php、Like/Movie.php
  2. 實作範例:
    • 安裝 Composer 至專案目錄內!(Windows 使用者可以參考這一篇)
      # yum install wget
      # cd /usr/share/nginx/html
      # wget https://getcomposer.org/installer -O composer-installer.php
      # php composer-installer.php --filename=composer --install-dir=/usr/local/bin
      # composer --version
      
    • 建立測試用目錄 :
      +Hello
      ++public
      ++-index.php
      ++src
      +++Cars
      +++-Car.php
      ++vendor (該目錄由 composer 自建,一開始不用手動建立)
      +++composer
      ++-autoload.php
      +-composer.json
      
    • 編寫 composer.json
      {
        "autoload": {
          "psr-4": {
            "Cars\\": "src/Cars"
          }
        }
      }
      
    • 初次建立名稱空間
      # composer dump-autoload
      
    • 開始建立 PHP 類別程式
      • 建立 Cars/Car.php
        <?php
        namespace Cars;
        
        class Car{
        
          protected $name;
        
          public function setName($name){
            $this->name = $name;
            return "completed...";
          }
        
          public function getName(){
            return $this->name;
          }
        }
        ?>
        
      • 建立 public/index.php
        <?php
        require_once '../vendor/autoload.php';
        
        use \Cars\Car;
        $mycar = new Car();
        $mycar->setName("Ford...");
        echo $mycar->getName();
        ?>
        
      • 使用瀏覽器 http://你的IP/Hello/public/index.php
    • 增加新的類別 : Customers
      • 在 src 目錄下建立新的目錄 Customers
        # mkdir /usr/share/nginx/html/Hello/src/Customers
        
      • 修改 composer.json
        • 加入 Customers 路徑的對應
          {
            "autoload": {
              "psr-4": {
                "Cars\\": "src/Cars",
                "Customers\\": "src/Customers"
              }
            }
          }
          
        • 再執行一次 composer
          # composer dump-autoload
          
        • 開始新增新的類別 Customer
          • 在 src/Customers 目錄下,新增 Customer.php
            <?php
            namespace Customers;
            
            class Customer{
              protected $cname;
              public function setName($cname){
                $this->cname = $cname;
                return "completed...";
              }
              
              public function getName(){
                return $this->cname;
              }
            }
            ?>
            
          • 修改 index.php 檔案內容
            <?php
            require_once '../vendor/autoload.php';
                
            use Cars\Car;
            use Customers\Customer;
                    
            $mycar = new Car();
            $mycar->setName("Ford...");
            echo "My Car: ".$mycar->getName();
            echo "
            "; $myprofile = new Customer(); $myprofile->setName("Peter"); echo "My Name: ".$myprofile->getName(); ?>
          • 在 Customers 下增加子目錄 Block
            # cd /usr/share/nginx/html/Hello/src
            # mkdir Customers/Block
            
          • 在 Block 目錄下,增加一個 Blocklist.php
            <?php
            namespace Customers\Block;
            
            use Customers\Customer;
            
            class Blocklist extends Customer {
            
              protected $state;
                    
              public function setState($state){
                $this->state = $state;
                return "Complete...";
              }
                    
              public function getState(){
                return $this->state;
              }
            }
            ?>
            
          • 修改 index.php 檔案內容
            <?php
            require_once '../vendor/autoload.php';
                
            use Cars\Car;
            use Customers\Customer;
            use Customers\Block\Blocklist;        
                    
            $mycar = new Car();
            $mycar->setName("Ford...");
            echo "My Car: ".$mycar->getName();
            echo "
            "; $myprofile = new Customer(); $myprofile->setName("Peter"); echo "My Name: ".$myprofile->getName(); echo "
            "; $mystate = new Blocklist(); $mystate->setState("Forzien..."); echo $mystate->getState(); ?>
          • 使用瀏覽器 http://你的IP/Hello/public/index.php

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