MENU

#01: Composer 加载原理 —— 准备

January 20, 2020 • Laravel 源码

目前大部分的新老 PHP 项目都在使用 Composer 作为文件自动加载工具及依赖管理工具。

前置知识

  • 命名空间
  • PSR0、PSR4 规范

测试项目

Composer 目前支持 PSR-4PSR-0classmapfile 共 4 中加载方式,其中 PSR-4 规范为推荐加载方式。为了实验我们先创建一个测试环境,看看每一种加载方式最终是如何工作的:

$ mkdir test-composer && cd test-composer
$ composer init

把每一种加载方式都定义一遍,在 composer.json 中填入以下内容:

{
    "autoload": {
        "psr-4": {
            "App\\": "app"
        },
        "psr-0": {
            "Service\\": ""
        },
        "classmap": [
            "other"
        ],
        "files": [
            "app/helper.php"
        ]
    }
}

接着创建所需的文件:

$ mkdir -p app/{Controller,Model}
$ make other service

$ touch app/Controller/HomeController.php
$ touch app/Model/User.php
$ touch other/HttpClient
$ touch service/EmailService.php
$ touch app/helper.php
$ touch index.php

编写相应的内容:

// app/Controller/HomeController.php
<?php

namespace App\Controller;

use App\Model\User;
use Other\HttpClient;
use Service\EmailService;

class HomeController
{
    public static function login()
    {
        $user = new User;

        $httpClient = new HttpClient;

        $emailService = new EmailService;
    }
}


// app/Model/User.php
<?php

namespace App\Model;

class User
{
}


// app/helper.php
<?php

function hello()
{
    echo "hello\n";
}


// other/HttpClient.php
<?php

namespace Other;

class HttpClient
{
}


// service/EmailService.php
<?php

namespace Service;

class EmailService
{
}


// index.php
<?php

use App\Controller\HomeController;

require_once './vendor/autoload.php';

hello();
HomeController::login();

运行 composer install,最终看起来是这样的:

├── app
│ ├── Controller
│ │ └── HomeController.php
│ ├── Model
│ │ └── User.php
│ └── helper.php
├── composer.json
├── index.php
├── other
│ └── HttpClient.php
├── service
│ └── EmailService.php
└── vendor
    ├── autoload.php
    └── composer
        ├── ClassLoader.php
        ├── LICENSE
        ├── autoload_classmap.php
        ├── autoload_files.php
        ├── autoload_namespaces.php
        ├── autoload_psr4.php
        ├── autoload_real.php
        ├── autoload_static.php
        └── installed.json

没有添加任何依赖,搞清楚 4 种加载是如何工作就够了。首先可以简单讲一下整个工作的过程,Composer 放在哪个项目都是一样的,不一样的是每个项目的目录情况,因此就有了第一步:引导,目的是将当前项目所需加载的情况(对应为数组)注入到核心加载类中;第二步:注册,这里涉及到 spl_autoload_register 的使用了,目的是使用 Composer 接管对未知类引用的处理;第三部:加载,对未知类的处理,根据完整的类名解析出文件路径,接着 include 相应文件。