composer 自动加载

webpenson, 20 十月, 2021

Composer是PHP中用来管理依赖(dependency)关系的工具。你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer会帮你安装这些依赖的库文件。

自动加载是指在代码中,不需要显式地使用文件路径将类库文件包含进来,便可使用该文件中定义的类库。

PHP的自动加载机制

PHP的自动加载可以使用__autoload()和spl_autoload_register()两种机制,但后一种为主流,原因是:

  • __autoload()是全局唯一的,如果框架占了这个名字,便会导致框架的用户用不了其它的__autoload()了,包括用户自定义的和其它类库带的。spl_autoload_register()可以注册多个autoload方法,不存在这个问题。

  • __autoload()是一个函数,在实际使用中,开发者势必要赋予它一些变量(例如class path和class_name => file_path mapping数组)。这就只能靠全局变量了,使用全局变量可不是好的编码习惯。spl_autoload_register()可以将一个Class的某个方法注册为autoload函数,如Symfony的spl_autoload_register(array(self::getInstance(), 'autoload'));

Composer的自动加载方式

Composer提供了四种自动加载的方式,分别是PSR-0、PSR-4、生成classmap以及直接包含files。

提到psr-0和psr-4就不得不先了解命名空间,命名空间的详细介绍详见底部《PHP手册:命名空间》[[1]](#php-namespace)。

  • psr-0方式,要求目录名称和命名空间层层对应,会导致目录结构容易变得比较深。虽然已被官方废弃,但因为主流框架都已实现psr-0,因此composer仍然使用psr-0来向下兼容。

        "autoload": {
             "psr-0": {
                 "Foo\\": "src/",
             }
        }
    

按照PSR-0的规则,当试图自动加载 "Foo\Bar\Baz" 这个class时,那么会去寻找"src/Foo/Bar/Baz.php",最终这个配置也以Map的形式写入生成的vendor/composer/autoload_namespaces.php

  • psr-4方式,是composer推荐使用的一种方式,也是psr-0的替代方案,因为它更易使用并能带来更简洁的目录结构。在composer.json里是这样进行配置的

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

按照PSR-4的规则,当试图自动加载 "Foo\Bar\Baz" 这个class时,会去寻找 "src/Bar/Baz.php" 这个文件。psr-4的配置换会被转换成namespace为key,dir path为value的Map的形式,并写入生成的 vendor/composer/autoload_psr4.php 文件之中

另外注意PSR-4和PSR-0的配置里,"Foo\"结尾的命名空间分隔符必须加上并且进行转义,以防出现"Foo"匹配到了"FooBar"这样的意外发生。

  • classmap方式,则是通过配置指定的目录或文件,然后在Composer安装或更新时,它会扫描指定目录下以.php或.inc结尾的文件中的class,生成class到指定file path的映射,并加入新生成的 vendor/composer/autoload_classmap.php 文件中。

        "autoload": {
            "classmap": ["src/", "lib/", "Something.php"]
        }
    

例如src/下有一个BaseController类,那么在autoload_classmap.php文件中,就会生成这样的配置:
'BaseController' => $baseDir . '/src/BaseController.php'

  • files方式,就是手动指定供直接加载的文件。比如说我们有一系列全局的helper functions,可以放到一个helper文件里然后直接进行加载

        "autoload": {
             "files": ["src/MyLibrary/functions.php"]
        }
    

它会生成一个array,包含这些配置中指定的files,再写入新生成的
vendor/composer/autoload_files.php

在composer.json配置完成之后,来到terminal执行
composer install
执行成功之后,composer就会帮你将加载机制创建完备,会得到一个vendor文件夹。

最后,只要在项目中
require 'vendor/autoload.php';
你所需要的所有类库都会在适当的时候自动载入。

参考资料

《PHP手册:命名空间》http://php.net/language.names...
《PHP手册:自动加载类》http://php.net/manual/zh/lang...
《细说“PHP类库自动加载”》https://github.com/qinjx/adv_...
《composer设计原理及用法》http://blog.turn.tw/?p=1039
《composer进阶原理:PHP命名空间与PSR-0》http://blog.turn.tw/?p=1122
《PHP管理依赖关系工具Composer的自动加载》http://www.jb51.net/article/5...

评论