Listening to the Words

composer自动加载--从零构建一个新项目

从零构建一个新项目

还记得php5.3的年代项目结构是什么样的吗?很多人都接触过Ecshop或者wordpress的源码吧,如果从零开始构建一个工程项目,你最花费精力的是什么?

相信很多人都是为项目路径而发愁,没错,作为一个脚本语言PHP要过于灵活,每一个脚本页面都必须是同 include或者require来引入路径。是不是很烦恼这个东西?

还得PSR规范出来之前,怎么命名类名的吗? A_B_C_D_E_F_CLASSNAME这样的类名是不是很常见?

后来PHP有了自动加载方法 spl_autoload_register(),这个系统函数帮助项目完成了类的自动加载。后来很多框架都基于它,譬如Thinkphp3.2等。

但是这样还是不够,随着工程的不断变大,项目需要引入更多的三方组件,于是这时自动加载的矛盾又出现了,每个框架都有不同的加载机制,使得三方组件的适配性大打折扣。

这时,一个叫做composer依赖管理包出现,它完全依赖于PSR4自动加载规范,核心仍然是spl_autoload_register,但是因为有了加载规范,每个开发者开发组件时都遵循这个规范,这样做带来的好处显而易见:每个同样遵循了PSR4自动加载规范的框架都可以自动适配组件。

在composer的推动下整个社区迎来了框架的大爆发,symfony以及laravel都是完全基于composer而成。

接下来我就尝试着自己创造一个能够自动加载的项目:

composer.json

想要实现自动加载,项目根目录下必须有一个composer.json文件:

{
    "name": "jeristiano/antiny",
    "description": "AintQueue demo",
    "type": "project",
    "license": "MIT",
    "authors": [
        {
            "name": "jeristiano",
            "email": "jeristianokuang@gmail.com"
        }
    ],
    "require": {
        "php": ">=7.2",
        "littlesqx/aint-queue": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "App\\": "app"
        }
    }
}

文件里定义了包的名字、作者等信息,重要的是requireautoload

  • require定义了整个项目的依赖关系,以及它所引用的其他三方组件
  • autoload 是自动加载的核心,"App\\": "app" 的意思是顶级命名空间的路径绑定在app目录下,只有这个目录下的文件能实现自动加载。

composer update

定义好了依赖关系,此时进入到项目根目录,执行命令

composer update

时间可能会很久,耐心等待。。。。

执行完,会发现项目里多个一个文件夹,vendor,所有的三方组件都集成在这里。

how does it work?

想要实现自动加载,就必须在入口文件中引入composer的自动加载类:

require __DIR__ . '/vendor/autoload.php';

这里面是啥?

<?php

// autoload.php @generated by Composer

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInitf68b3cadb48dd3584e4501abc9662b24::getLoader();

getLoader()里的核心就一句:
spl_autoload_register(array('ComposerAutoloaderInitf68b3cadb48dd3584e4501abc9662b24', 'loadClassLoader'), true, true);  

很熟悉了吧~

这时,就可以在app目录下写业务逻辑了:

<?php

namespace App\Controller;
/**
 * Class TestController
 * @package App\Controller
 */
class TestController
{
    /**
     * @return array
     */
    public function __invoke ()
    {
        return [
            "config" => [1, 2, 3],
            TestController::class => TestController::class,
        ];
    }

}

这时一个测试脚本,注意它的命名空间,实际路径是:app/Controller/TestController.php

测试下能不能自动加载:

<?php

/*
 * This file is part of the littlesqx/aint-queue.
 *
 * (c) littlesqx <littlesqx@gmail.com>
 *
 * This source file is subject to the MIT license that is bundled.
 */

use App\Controller\TestController;

require __DIR__ . '/vendor/autoload.php';
$ss= (new TestController())();
var_dump($ss);

接着使用PHP内置的服务器启动:

php -S 192.168.10.10:8080 index.php

输出结果:

home/vagrant/code/ant/index.php:16:
array (size=2)
  'config' => 
    array (size=3)
      0 => int 1
      1 => int 2
      2 => int 3
  'App\Controller\TestController' => string 'App\Controller\TestController' (length=29)

这样就实现了自动加载,是不是比上时代容易的多了?~

点赞