2019年2月26日

PHP Composer Autoload PSR-0、PSR-4與classmap的差別及autoload optimize

PSR-0PSR-4都是PHP-FIG制定的PHP Autoloader標準,而透過composer的協助,開發者可以方便的使用這些Autoloader。

所謂的autoloader自然就是提供自動載入類別的功能,開發者不需要自己在每支檔案前reuqire或include所有需要的類別。

PSR-0、PSR-4

PSR-0PSR-4類別的位置遵照PHP-FIG的規範放置即可,其中PSR-0是比較舊的規範,目前主流是PSR-4

想要讓composer使用PSR-4來幫你自動載入可以在composer.json中加入autoload psr-4的設定

"autoload": {
    "psr-4": {
        "App\\": "src/"
    },
}

其中App是Namespace,src/檔案所在目錄。

設定完之後要先執行composer指令,讓composer自動產生autoloader:

composer dump-autoload

之後我們就可以在src自由的新增類別了。比如在src目錄中新增一個Demo.php檔案

/src/demo.php

<?php
namespace App;

class Demo
{
  //...
}

在其他程式中開發者可以直接使用此類別,不用在程式碼中輸入類別檔案路徑。

<?php

$demo = new \App\Demo();

PSR-0用法差不多,只是路徑規則不同。詳情可參考官方文件PSR-0: Autoloading Standard PSR-4

classmap

classmap是composer提供的另外一種autoload方式,跟PSR-0PSR-4最主要的差別在於,classmap沒辦法主動尋找類別所對應的檔案路徑,而是透過維護一份對照表的方式,透過此對照表來找到類別檔案的路徑並載入類別。

要使用classmap可以在composer.json中加入classmap的設定,其中others/代表目錄位置。

"autoload": {
    "classmap": [
        "others/",
    ]
}

如果others目錄中有Helper.php這隻檔案:

/others/Helper.php

<?php
namespace App;

class Helper
{
  //...
}

那麼當我們設定完composer.json後,執行composer dump-autoload,composer便會產生一類似這樣的對照表:

'App\\Helper' => '/others/Helper.php',

告訴我們Helper類別的所在位置。這樣其他程式就可以直接使用這個類別了。

<?php

$helper = new \App\Helper();

但是當我們在執行完composer dump-autoload後,又在others中新增別的類別檔案,因為對照表中沒有這個新增的類別對應,我們必須要再執行一次composer dump-autoload,更新對照表才行。

PSR-0、PSR-4 Optimize

由於這兩個PHP-FIG規範可以達到自動尋找類別路徑的功能,這樣的功能會造成PHP使用比較大量的IO去檢查類別是否存在於某些規定的地方。因此composer提供了自動載入最佳化的方法,

composer dump-autoload --optimize

或是

composer dump-autoload -o

透過這樣的方式,composer會替PSR-0PSR-4的類別產生類似classmap方式的對照表,這麼一來PHP就可以透過此對照表,來快速地找到類別位置了。

但是跟classmap不同的地方在於,後續新增的檔案只要符合PHP-FIG的規範,依舊可以被自動探尋到,不必每次都dump-autoload,只是若是對於已經產生對照表的類別進行檔案位置的搬動或名稱的修改,就必須要重新執行dump-autoload,否則對照表會對照到錯誤的位置,而無法順利載入。