详解composer的自动加载机制

composer是一个用PHP开发的用来管理项目依赖的工具,当你在项目中声明了依赖关系后,composer可以自动帮你下载和安装这些依赖库,并实现自动加载代码。




安装composer

composer的安装非常的容易

1.下载安装脚本,这里把安装脚本保存为 composer-setup.php

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

2. 然后执行运行安装脚本,然后会生成一个可执行的phar包文件composer.phar(类似java中的.jar包)


[root@localhost composer]# php composer-setup.php 
All settings correct for using Composer
Downloading...

Composer (version 1.5.2) successfully installed to: /root/composer/composer.phar
Use it: php composer.phar

[root@localhost composer]# ls
composer.phar  composer-setup.php

3.执行命令: php composer.phar,  显示如下信息说明安装成功,注意最好不要使用root账户来执行composer命令,否则会报警告:

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

[root@localhost composer]# php composer.phar 
Do not run Composer as root/super user! See https://getcomposer.org/root for details
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 1.5.2 2017-09-11 16:59:25

Usage:
  command [options] [arguments]

Options:
  -h, --help                     Display this help message
.....

4. 如果想让composer在任意目录下都可以执行,可以执行命令:mv composer.phar /usr/local/bin/composer ,将 composer.phar 放到系统环境变量之下并重命名为composer,  之后便可以在任意目录使用 composer 来代替 php composer.phar 命令

[root@localhost composer]# mv composer.phar /usr/local/bin/composer
[root@localhost composer]# cd ~
[root@localhost ~]# composer
Do not run Composer as root/super user! See https://getcomposer.org/root for details
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
.....

配置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 文件,并输入以下内容:

{
    "require": {
        "monolog/monolog": "1.0.*"
    }
}

然后输入命令 composer install,composer会帮我们自动下载monolog库,一般依赖库会默认放在项目的vendor目录下

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

composer的自动加载

composer不仅仅帮我们处理依赖,还帮我们实现了自动加载。在vendor目录下有一个autoload.php, 只要在我们的项目中引入这个文件就可以自动加载依赖库。


项目根目录下新建一个index.php, 并输入以下测试代码:

<?php
require 'vendor/autoload.php';

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$log = new Logger('demo');
$log->pushHandler(new StreamHandler('app.log', Logger::WARNING));
$log->addWarning("this is a warning log!");

测试是否运行正常:

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

可以看到monolog库完全不需要我们手动去加载,只需要使用正确的命名空间,composer的自动加载机制会帮我们找到对应的文件并加载。

对于依赖库,composer帮我们处理好了自动加载,那对于我们自己的项目文件该怎么实现自动加载呢,比如现在在我的项目根目下创建一个 controllers 目录存放控制器,并在该目录下新建一个Controller.php, 代码如下:

<?php
namespace controllers;

class Controller
{
    public function test()
    {
        echo "Controller::test\n";
    }
}

现在如何在index.php中自动加载这个 Controller 类呢,如果我们直接在index.php写

<?php
require 'vendor/autoload.php';
use controllers\Controller;

$c = new Controller();
$c->test();

上面代码肯定是无法找到Controller类的:

[root@localhost demo]# php index.php 
PHP Fatal error:  Uncaught Error: Class 'controllers\Controller' not found in /root/demo/index.php:6
Stack trace:
#0 {main}
  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" 项:

{
    "require": {
        "monolog/monolog": "1.0.*"
    },
    "autoload": {
        "files": ["controllers/Controller.php"]
    }
}
需要加载哪个文件,直接写入文件路径即可,路径相对项目的根目录。然后执行composer dump-autoload,该命令可以遍历我们项目根目录以及各依赖库下的 composer.json 文件然后重新生成 vendor/composer/autoload_* 跟自动加载相关的配置文件

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

此时composer会帮我们更新自动加载相关的配置文件,composer dump-autoload 之后composer会把配置值写入与 Files加载方式对应的 vendor/composer/autoload_files.php 配置文件中:

[root@localhost demo]# cat vendor/composer/autoload_files.php 
<?php

// autoload_files.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    '0b001b283842589bdffd092a1d29de66' => $baseDir . '/controllers/Controller.php',
);

此时再运行index.php就一切正常了

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

2. Classmap 加载方式也很简单,composer会搜寻我们指定的目录或文件,并把搜寻到的结果写到Classmap对应的 vendor/composer/autoload_classmap.php 配置文件中。 修改composer.json :

{
    "require": {
        "monolog/monolog": "1.0.*"
    },
    "autoload": {
        "classmap": ["controllers/"]
    }
}

以上配置会让composer搜寻 controllers 目录下的所有类,并生成配置文件,同样先 composer dump-autoload 下:

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

[root@localhost demo]# cat vendor/composer/autoload_classmap.php 
<?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'controllers\\Controller' => $baseDir . '/controllers/Controller.php',
);


此时发现之前生成的 vendor/composer/autoload_files.php 配置文件也被 composer 删除了(由于项目中没再使用到Files的加载方式)

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

测试结果:

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

3. PSR-0 ,这种加载方式已经过时,所以不推荐在新项目中使用,请用 PSR-4 来代替它。

修改composer.json 如下, 然后执行composer dump-autoload

{
    "require": {
        "monolog/monolog": "1.0.*"
    },
    "autoload": {
        "psr-0": {"controllers\\": ""}
    }
}

以上配置的意思是指定 controllers命名空间 所在的父级目录,由于controllers命名空间所在的父级目录就是项目根目录, 所以配置值用 "" ,composer dump-autoload后配置会写入 PSR-0对应的 vendor/composer/autoload_namespaces.php 配置文件中,而且从配置文件中可以看到之前使用的 monolog 也是使用 遵循PSR-0 规范的自动加载

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

[root@localhost demo]# cat vendor/composer/autoload_namespaces.php
<?php

// autoload_namespaces.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'controllers\\' => array($baseDir . '/'),
    'Monolog' => array($vendorDir . '/monolog/monolog/src'),
);
[root@localhost demo]# php index.php 
Controller::test

4. PSR-4  是 PSR-0 的升级版,是目前推荐的自动加载方式,这种方式使用的是按需加载。

修改composer.json 如下:

{
    "require": {
        "monolog/monolog": "1.0.*"
    },
    "autoload": {
        "psr-4": {"controllers\\": "controllers/"}
    }
}

注意和PSR-0 的 composer.json 做对比,PSR-4 和 PSR-0 的主要区别是,PSR-4指定的就当作当前命名空间的目录, 而PSR-0 指定的是当前命名空间的父目录。composer dump-autoload 一下, 配置会写入PSR-4对应的 vendor/composer/autoload_psr4.php 文件中


[root@localhost demo]# cat vendor/composer/autoload_psr4.php 
<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'controllers\\' => array($baseDir . '/controllers'),
);

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


以上就是对composer的四种自动加载方式的简单介绍,这里主要偏向于使用,至于代码的实现,大家可以阅读 vendor/autoload.php 以及 vendor/composer/ 目录下的相关代码,有时间我再单独写一篇composer自动加载机制实现的源码分析^^

That's it!


此文为原创,转载请注明出处 :http://blog.csdn.net/zhang197093/article/details/78118491


  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值