詳解composer的自動加載機制

composer是一個用PHP開發的用來管理項目依賴的工具,當你在項目中聲明瞭依賴關係後,composer能夠自動幫你下載和安裝這些依賴庫,並實現自動加載代碼。php

 


 

安裝composerjava

composer的安裝很是的容易git

1.下載安裝腳本,這裏把安裝腳本保存爲 composer-setup.phpgithub

 

  1. [root@localhost composer] # php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');"
  2. [root@localhost composer] # ls
  3. composer-setup.php


2. 而後執行運行安裝腳本,而後會生成一個可執行的phar包文件composer.phar(相似java中的.jar包)編程

 

  1. [ root@localhost composer]# php composer-setup.php
  2. All settings correct for using Composer
  3. Downloading...
  4.  
  5. Composer (version 1.5.2) successfully installed to: /root/composer/composer.phar
  6. Use it: php composer.phar
  7.  
  8. [ root@localhost composer]# ls
  9. composer.phar composer-setup.php

 

3.執行命令: php composer.phar,  顯示以下信息說明安裝成功,注意最好不要使用root帳戶來執行composer命令,不然會報警告:json

Do not run Composer as root/super user! See https://getcomposer.org/root for details網絡

 

  1. [root@localhost composer] # php composer.phar
  2. Do not run Composer as root/super user! See https://getcomposer.org/root for details
  3. _____ _
  4. / ___ _/___ ____ ___ ____ ____ ________ _____
  5. / / / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
  6. / /___/ /_/ / / / / / / /_/ / /_/ (__ ) __/ /
  7. \____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
  8. /_/
  9. Composer version 1.5.2 2017-09-11 16:59:25
  10.  
  11. Usage:
  12. command [options] [arguments]
  13.  
  14. Options:
  15. -h, --help Display this help message
  16. .....
  17.  


4. 若是想讓composer在任意目錄下均可以執行,能夠執行命令:mv composer.phar /usr/local/bin/composer ,將 composer.phar 放到系統環境變量之下並重命名爲composer,  以後即可以在任意目錄使用 composer 來代替 php composer.phar 命令
app

 

  1. [root@localhost composer] # mv composer.phar /usr/local/bin/composer
  2. [root@localhost composer] # cd ~
  3. [root@localhost ~] # composer
  4. Do not run Composer as root/super user! See https://getcomposer.org/root for details
  5. _____ _
  6. / ___ _/___ ____ ___ ____ ____ ________ _____
  7. / / / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
  8. / /___/ /_/ / / / / / / /_/ / /_/ (__ ) __/ /
  9. \____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
  10. .....
  11.  

 

配置composer使用國內鏡像庫composer

因爲國內特殊的網絡環境,訪問國外的官方鏡像庫每每速度很慢,甚至無響應,因此咱們配置使用composer中文網(http://www.phpcomposer.com)提供的國內鏡像庫,執行如下命令便可框架

 

[zyee@localhost root]$ composer config -g repo.packagist composer https://packagist.phpcomposer.com

 

簡單的composer.json

假設咱們如今的項目根目錄爲demo,而且咱們的項目依賴 monolog(https://github.com/Seldaek/monolog) 這個php日誌庫,這時咱們能夠在項目根目錄創建一個 composer.json 文件,並輸入如下內容:

 

  1. {
  2. "require": {
  3. "monolog/monolog": "1.0.*"
  4. }
  5. }


而後輸入命令 composer install,composer會幫咱們自動下載monolog庫,通常依賴庫會默認放在項目的vendor目錄下

 

  1. [ root@localhost demo]# ls
  2. composer.json
  3. [ root@localhost demo]# composer install
  4. Do not run Composer as root/super user! See https://getcomposer.org/root for details
  5. Loading composer repositories with package information
  6. Updating dependencies (including require-dev)
  7. Package operations: 1 install, 0 updates, 0 removals
  8. Failed to download monolog/monolog from dist: The zip extension and unzip command are both missing, skipping.
  9. The php.ini used by your command-line PHP is: /etc/php.ini
  10. Now trying to download from source
  11. - Installing monolog/monolog (1.0.2): Cloning b704c49a30
  12. Writing lock file
  13. Generating autoload files
  14. [root@localhost demo]# ls
  15. composer.json composer.lock vendor


composer的自動加載

composer不只僅幫咱們處理依賴,還幫咱們實現了自動加載。在vendor目錄下有一個autoload.php, 只要在咱們的項目中引入這個文件就能夠自動加載依賴庫。


項目根目錄下新建一個index.php, 並輸入如下測試代碼:

 

  1. <?php
  2. require 'vendor/autoload.php';
  3.  
  4. use Monolog\Logger;
  5. use Monolog\Handler\StreamHandler;
  6.  
  7. $log = new Logger('demo');
  8. $log->pushHandler( new StreamHandler('app.log', Logger::WARNING));
  9. $log->addWarning( "this is a warning log!");


測試是否運行正常:

 

  1. [root@localhost demo]# php index.php
  2. [root@localhost demo]# ls
  3. app.log composer.json composer.lock index.php vendor
  4. [root@localhost demo]# cat app.log
  5. [2017-09-28 00:32:27] demo.WARNING: this is a warning log! [] []


能夠看到monolog庫徹底不須要咱們手動去加載,只須要使用正確的命名空間,composer的自動加載機制會幫咱們找到對應的文件並加載。

對於依賴庫,composer幫咱們處理好了自動加載,那對於咱們本身的項目文件該怎麼實現自動加載呢,好比如今在個人項目根目下建立一個 controllers 目錄存放控制器,並在該目錄下新建一個Controller.php, 代碼以下:

 

  1. <?php
  2. namespace controllers;
  3.  
  4. class Controller
  5. {
  6. public function test()
  7. {
  8. echo "Controller::test\n";
  9. }
  10. }


如今如何在index.php中自動加載這個 Controller 類呢,若是咱們直接在index.php寫

 

  1. <?php
  2. require 'vendor/autoload.php';
  3. use controllers\Controller;
  4.  
  5. $c = new Controller();
  6. $c->test();

 

上面代碼確定是沒法找到Controller類的:

  1. [root@localhost demo]# php index.php
  2. PHP Fatal error: Uncaught Error: Class 'controllers\Controller' not found in /root/demo/index.php:6
  3. Stack trace:
  4. #0 {main}
  5. thrown in /root/demo/index.php on line 6

 

要想解決上述這個問題咱們首先須要瞭解下composer的自動加載機制。

composer支持四種自動加載的方式:PSR-0PSR-4 /ClassmapFiles , 其中 PSR-4 是當前推薦的加載方式。

 

什麼是 PSR ?

PSR 是 PHP Standards Recommendations(PHP 標準建議)的縮寫,這是一個叫作 PHP Framework Interop Group(http://www.php-fig.org/) 的組織所推出的關於PHP編程方面的一些標準建議,這個組織的成員包括一些知名的框架和項目,好比 CakePHP,Drupal,Magento,Symfony,Yii framework,Zend Framework 2等等,固然也包括這裏說的 composer,該組織曾推出了一系列的 PSR, 具體的有哪些請參考 http://www.php-fig.org/psr/ , 其中 PSR-0 http://www.php-fig.org/psr/psr-0/)和 PSR-4http://www.php-fig.org/psr/psr-4/)是關於自動加載方面作出的一些規範

 

1. Files 是最簡單的加載方式,這種方式無論加載的文件是否用到始終都會加載,而不是按需加載

修改項目根目下的composer.json, 加入 "autoload" 項:

 

  1. {
  2. "require": {
  3. "monolog/monolog": "1.0.*"
  4. },
  5. "autoload": {
  6. "files": ["controllers/Controller.php"]
  7. }
  8. }

須要加載哪一個文件,直接寫入文件路徑便可,路徑相對項目的根目錄。而後執行composer dump-autoload,該命令能夠遍歷咱們項目根目錄以及各依賴庫下的 composer.json 文件而後從新生成 vendor/composer/autoload_* 跟自動加載相關的配置文件

 

  1. [root@localhost demo] # composer dump-autoload
  2. Do not run Composer as root/super user! See https://getcomposer.org/root for details
  3. Generating autoload files

此時composer會幫咱們更新自動加載相關的配置文件,composer dump-autoload 以後composer會把配置值寫入與 Files加載方式對應的 vendor/composer/autoload_files.php 配置文件中:

  1. [root@localhost demo] # cat vendor/composer/autoload_files.php
  2. <?php
  3.  
  4. // autoload_files.php @generated by Composer
  5.  
  6. $vendorDir = dirname(dirname( __FILE__));
  7. $baseDir = dirname($vendorDir);
  8.  
  9. return array(
  10. '0b001b283842589bdffd092a1d29de66' => $baseDir . '/controllers/Controller.php',
  11. );


此時再運行index.php就一切正常了

 

  1. [root@localhost demo]# php index.php
  2. Controller::test

 

2. Classmap 加載方式也很簡單,composer會搜尋咱們指定的目錄或文件,並把搜尋到的結果寫到Classmap對應的 vendor/composer/autoload_classmap.php 配置文件中。 修改composer.json :

 

  1. {
  2. "require": {
  3. "monolog/monolog": "1.0.*"
  4. },
  5. "autoload": {
  6. "classmap": ["controllers/"]
  7. }
  8. }


以上配置會讓composer搜尋 controllers 目錄下的全部類,並生成配置文件,一樣先 composer dump-autoload 下:

 

  1. [root@localhost demo] # composer dump-autoload
  2. Do not run Composer as root/super user! See https://getcomposer.org/root for details
  3. Generating autoload files
  4.  
  5. [root@localhost demo] # cat vendor/composer/autoload_classmap.php
  6. <?php
  7.  
  8. // autoload_classmap.php @generated by Composer
  9.  
  10. $vendorDir = dirname(dirname( __FILE__));
  11. $baseDir = dirname($vendorDir);
  12.  
  13. return array(
  14. 'controllers\\Controller' => $baseDir . '/controllers/Controller.php',
  15. );

 

此時發現以前生成的 vendor/composer/autoload_files.php 配置文件也被 composer 刪除了(因爲項目中沒再使用到Files的加載方式)

 

  1. [root@localhost demo]# ll vendor/composer/
  2. 總用量 44
  3. -rw-r--r-- 1 root root 222 9月 28 01:59 autoload_classmap.php
  4. -rw-r--r-- 1 root root 210 9月 28 01:59 autoload_namespaces.php
  5. -rw-r--r-- 1 root root 143 9月 28 01:59 autoload_psr4.php
  6. -rw-r--r-- 1 root root 1762 9月 28 01:59 autoload_real.php
  7. -rw-r--r-- 1 root root 867 9月 28 01:59 autoload_static.php
  8. -rw-r--r-- 1 root root 13451 9月 28 01:59 ClassLoader.php
  9. -rw-r--r-- 1 root root 1375 9月 28 01:59 installed.json
  10. -rw-r--r-- 1 root root 1070 9月 28 01:59 LICENSE

測試結果:

  1. [root@localhost demo]# php index.php
  2. Controller::test


3. PSR-0 ,這種加載方式已通過時,因此不推薦在新項目中使用,請用 PSR-4 來代替它。修改composer.json 以下, 而後執行composer dump-autoload

  1. {
  2. "require": {
  3. "monolog/monolog": "1.0.*"
  4. },
  5. "autoload": {
  6. "psr-0": {"controllers\\": ""}
  7. }
  8. }


以上配置的意思是指定 controllers命名空間 所在的父級目錄,因爲controllers命名空間所在的父級目錄就是項目根目錄, 因此配置值用 "" ,composer dump-autoload後配置會寫入 PSR-0對應的 vendor/composer/autoload_namespaces.php 配置文件中,並且從配置文件中能夠看到以前使用的 monolog 也是使用 遵循PSR-0 規範的自動加載

 

  1. [root@localhost demo] # composer dump-autoload
  2. Do not run Composer as root/super user! See https://getcomposer.org/root for details
  3. Generating autoload files
  4.  
  5. [root@localhost demo] # cat vendor/composer/autoload_namespaces.php
  6. <?php
  7.  
  8. // autoload_namespaces.php @generated by Composer
  9.  
  10. $vendorDir = dirname(dirname( __FILE__));
  11. $baseDir = dirname($vendorDir);
  12.  
  13. return array(
  14. 'controllers\\' => array($baseDir . '/'),
  15. 'Monolog' => array($vendorDir . '/monolog/monolog/src'),
  16. );
  17. [root@localhost demo] # php index.php
  18. Controller::test


4. PSR-4  是 PSR-0 的升級版,是目前推薦的自動加載方式,這種方式使用的是按需加載。

修改composer.json 以下:

 

  1. {
  2. "require": {
  3. "monolog/monolog": "1.0.*"
  4. },
  5. "autoload": {
  6. "psr-4": {"controllers\\": "controllers/"}
  7. }
  8. }


注意和PSR-0 的 composer.json 作對比,PSR-4 和 PSR-0 的主要區別是,PSR-4指定的就看成當前命名空間的目錄, 而PSR-0 指定的是當前命名空間的父目錄。composer dump-autoload 一下, 配置會寫入PSR-4對應的 vendor/composer/autoload_psr4.php 文件中

 

  1. [root@localhost demo] # cat vendor/composer/autoload_psr4.php
  2. <?php
  3.  
  4. // autoload_psr4.php @generated by Composer
  5.  
  6. $vendorDir = dirname(dirname( __FILE__));
  7. $baseDir = dirname($vendorDir);
  8.  
  9. return array(
  10. 'controllers\\' => array($baseDir . '/controllers'),
  11. );
  12.  
  13. [root@localhost demo] # php index.php
  14. Controller::test



以上就是對composer的四種自動加載方式的簡單介紹,這裏主要偏向於使用,至於代碼的實現,你們能夠閱讀 vendor/autoload.php 以及 vendor/composer/ 目錄下的相關代碼,有時間我再單獨寫一篇composer自動加載機制實現的源碼分析^^

That's it!

 

此文爲原創,轉載請註明出處 :http://blog.csdn.net/zhang197093/article/details/78118491

相關文章
相關標籤/搜索