寫 PHP 最麻煩的就是 require/includ 檔案了。如今只要照著 PSR-4 的規範實作,就可以使用 Composer 提供的 autoload,自動載入相對應的檔案。
介紹
PSR-4 Autoloader 規範描述了如何架構專案的目錄結構及如何使用命名空間,遵循這個規範並搭配 Composer 提供的 autoload 就可以完成自動載入的動作。要使用 PSR-4 Autoloader 必須使用正確的命名空間。這裡的類別泛指類別(classes)、介面(interfaces)、特性(traits)等等相似的結構。
一個完整的類別名稱的形式如下:
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
- 完整的類別名稱(fully qualified class name)必須有最高層級(top-level)的命名空間(namespace),通常稱這個命名空間為「供應商命名空間(vendor namespace)」。
- 完整的類別名稱可以有一個或多個子命名空間。
- 一個完整的類別名稱必須以類別名稱結束。
- 在完整的類別名稱中,底線沒有其他意義。
- 完整的類別名稱可以由英文字母大小寫組合而成。
- 所有的類別名稱必須是有區分大小寫的。
- 在「完整的類別名稱」中,由一個或多個連續的「前置命名空間」及「子命名空間」組成。將「前置命名空間」中包含的分隔符號去除,表示為命名空間的前綴(prefix)名稱,它會對應到至少一個實體目錄,該目錄就稱為基底目錄(base directory)。
- 在「前置命名空間」之後的子命名空間,會對應到基底目錄下的子目錄。命名空間的分隔符號表示為目錄的階層,意思是子目錄必須對應到子命名空間。
- 最終的類別名稱,會對應到實體的
.php
檔案名稱,該檔案名稱的大小寫必須和類別名稱相同。
看幾個範例就能找出規則了。
範例 1:
完整類別名稱 | \Acme\Log\Writer\File_Writer |
---|---|
命名空間前置名稱 | Acme\Log\Writer |
基底目錄 | ./acme-log-writer/lib/ |
檔案路徑 | ./acme-log-writer/lib/File_Writer.php |
範例 2:
完整類別名稱 | \Aura\Web\Response\Status |
---|---|
命名空間前置名稱 | Aura\Web |
基底目錄 | /path/to/aura-web/src/ |
檔案路徑 | /path/to/aura-web/src/Response/Status.php |
範例 3:
完整類別名稱 | \Symfony\Core\Request |
---|---|
命名空間前置名稱 | Symfony\Core |
基底目錄 | ./vendor/Symfony/Core/ |
檔案路徑 | ./vendor/Symfony/Core/Request.php |
範例 4:
完整類別名稱 | \Zend\Acl |
---|---|
命名空間前置名稱 | Zend |
基底目錄 | /usr/includes/Zend/ |
檔案路徑 | /usr/includes/Zend/Acl.php |
規則就是,
因為:命名空間前置名稱 = 基底目錄
於是:(完整類別名稱 - 命名空間前置名稱) = (檔案路徑 - 基底目錄)
而且:完整類別名稱 最後一個分隔符號之後的名稱 = 檔案路徑 最後一個分隔符號之後的名稱.php = 類別名稱
實作
專案都依照 PSR-4 來架構後,就可以使用 Composer 來自動載入相關的檔案了。設定
首先,假設有一個新專案叫 demo,目錄名稱就叫 demo,其下有兩個子目錄:src 及 public,結構如下:
demo
/src
/public
在根目錄下建立 composer.json,內容如下:
JSON{
"autoload": {
"psr-4": {
"Tonycube\\": "src/Tonycube"
}
}
}
這裡表示要使用 PSR-4 標準的 autoload,"Tonycube" 表示「命名空間前置名稱」,對應到實體目錄的 "src/Tonycube",所以我們要在 src 目錄下建一個子目錄 Tonycube。目前的檔案結構如下:
demo
/src
/Tonycube
/public
composer.json
這裡先確定你已經有安裝 composer。在終端機下,進入 demo 目錄,接著輸入
composer dump-autoload
成功的話,會建立一個 vendor 目錄,內含 autoload.php:
demo
/src
/Tonycube
/public
/vendor
autoload.php
/composer
composer.json
之後的 PHP 檔案只要 require 這個 autoload.php 檔,就可以自動載入相對應的 PHP 檔案,不用再老是寫一堆 require 了。程式碼
假設在 Tonycube 目錄下再建立一個目錄 Hello,然後在其中建 3 個示範檔案,如下:src/Tonycube/Hello/World.php
PHP<?php
namespace Tonycube\Hello;
class World
{
function __construct()
{
echo 'Hello World ~'.PHP_EOL;
}
}
src/Tonycube/Hello/Tony.php
PHP<?php
namespace Tonycube\Hello;
class Tony
{
function __construct()
{
echo 'Hello Tony ~'.PHP_EOL;
}
}
src/Tonycube/Hello/Any.php
PHP<?php
namespace Tonycube\Hello;
class Any
{
function __construct($name)
{
echo 'Hello '.$name.PHP_EOL;
}
}
這樣就建立了 3 個可以被使用的類別。接著在 public 下,建立一個 index.php :
PHP<?php
require '../vendor/autoload.php';
use \Tonycube\Hello\World as World;
use \Tonycube\Hello;
$world = new World();
$tony = new Hello\Tony();
$any = new \Tonycube\Hello\Any('Amy');
首先會 require vendor 目錄中的 autoload.php,由它來幫我們執行自動載入的工作。這裡示範 3 種在命名空間下使用類別的方式。
- use … as … :表示使用完整類別名稱,並且使用 as 建立別名,之後就可以直接使用這個別名。
- use :可以使用完整類別名稱,這樣在 new 的時候,只要寫類別名稱即可。或是像這個範例,只寫到子命名空間 Hello,這樣之後在 new 的時候,就必須包含這個子命名空間。
- 不使用 use:這樣 new 的時候就必須使用完整類別名稱。
執行
如果這個專案是放在伺服器目錄的話,可以在瀏覽器上輸入以下連結:http://localhost/demo/public/index.php
或是在終端機,進入 public 目錄下:
php index.php
註:你必須先把 php 指令加入環境變數中。最終檔案結構:
demo
/src
/Tonycube
/Hello
Any.php
Tony.php
World.php
/public
index.php
/vendor
autoload.php
/composer
composer.json
更新 autoload 內容
很重要,如果你有修改過 composer.json 裡的 autoload 的內容(或第一次使用),記得必須在終端機輸入:composer dump-autoload
讓 Composer 把資料更新,至於它是更新哪個檔案的內容,你可以打開:
vendor/composer/autoload_psr4.php
這個檔案,回傳的陣列值中,就會包含我們所指定的內容。相關影片
這部影片的說明很詳細,把舊的 require 檔案方式到使用 PSR-4 autoloader 的過程講了一遍。
本文網址:http://blog.tonycube.com/2016/09/php-psr-4-autoloader.html
由 Tony Blog 撰寫,請勿全文複製,轉載時請註明出處及連結,謝謝 😀
由 Tony Blog 撰寫,請勿全文複製,轉載時請註明出處及連結,謝謝 😀
我要留言
留言小提醒:
1.回覆時間通常在晚上,如果太忙可能要等幾天。
2.請先瀏覽一下其他人的留言,也許有人問過同樣的問題。
3.程式碼請先將它編碼後再貼上。(線上編碼:http://bit.ly/1DL6yog)
4.文字請加上標點符號及斷行,難以閱讀者恕難回覆。
5.感謝您的留言,您的問題也可能幫助到其他有相同問題的人。