• Laravel 学习笔记之 Composer 自动加载


    说明:本文主要以Laravel的容器类Container为例做简单说明Composer的自动加载机制。

    Composer的自动加载机制

    1、初始化一个composer项目

    在一个空目录下composer安装Laravel的容器Container包:

    composer require illuminate/container

    然后在该目录下新建一个index.php文件,然后分析下Container类为何能被实例化:

    <?php
    /**
     * Created by PhpStorm.
     * User: liuxiang
     * Date: 16/5/12
     * Time: 19:59
     */
    require_once __DIR__.'/vendor/autoload.php';
    
    $container = new IlluminateContainerContainer();
    var_dump($container);

    2、分析下composer加载类的流程

    图片描述

    使用composer最大的好处是只需最开始require一个autoload.php文件,就可以new你所需要的类了,不再需要传统的方式A文件内各种include跳到B文件又各种include,非常头疼。

    Composer按照四种规范来加载文件:

    • psr-4
    • psr-0(这种规范某些部分不是很优雅)
    • classmap(命名空间和文件路径的映射)
    • files

    ComposerAutoloaderInit88609474169d8656473fa0223c682a7a这个类是composer为了防止类冲突搞了一个命名ComposerAutoloaderInit+hash,不管咋样,require_once这个类后需要返回的是一个加载器$loader,而这个加载器经过四种规范遍历后,由null被填充为含有各种变量值的ClassLoader对象。

    如果仔细观察autoload_classmap.php、autoload_namespaces.php、autoload_psr4.php和autoload_files(这里用了Container包是没有这个文件的,但Laravel整个项目是有的)文件后,这些都按照对应的规范返回要么命名空间与路径的映射,要么完整路径与某个哈希的映射。

    从上图中能看出这个composer初始化路径的流程,重点是ClassLoader这个类的loadClass($class)这个方法,是通过spl_autoload_register这个PHP自动加载函数来注册到autoload函数栈中,最后返回一个$loader加载器,而这个加载器是包含一些私有变量的,由于本Container包只包含IlluminateContainer和IlluminateContracts,且都是psr-4规范,则私有变量$prefixLengthsPsr4和$prefixDirsPsr4就包含了命名空间路径映射的数组值,其余私有变量就是空。

    最后返回一个加载器$loader,然后需要实例化一个类时,就会根据loadClass($class)来寻找对应的文件,看下文。

    Container类的实例化过程#

    图片描述

    $loader这个加载器已经有了,而且它还是塞满了各种私有变量,这些变量值为命名空间路径映射或者路径哈希映射等,当然这里只有命名空间路径映射这种psr-4规范了。也就是说,一句require_once这个autoload.php文件后就拿到了一个饱满的$loader,然后现在开始new一个类Container,那如何找到这个Container.php文件路径的呢?

    从第二个序列图就可看出,首先调用ClassLoader中的loadClass()这个函数来找文件路径,传入的$class变量值是“IlluminateContainerContainer”这个字符串,然后又继续调用findFile($class)函数先做classmap查找,然后进入findFileWithExtension($class,'.php')中做psr-4/psr-0查找,其实就是搜寻这些私有变量值,比如这里Container类是psr-4规范,那就去$prefixLengthsPsr4/$prefixDirsPsr4这些psr-4私有变量中查找文件绝对路径,返回一个$file,再include下就等于这个类可以被实例化了。当然,这里Container.php文件绝对路径被找到后,发现它还实现了一个接口ContractContainer,那就再去同样方式找这个文件:psr-4根据命名空间IlluminateContractsContainerContainer去找这个接口对应的绝对路径。

    总之,当实例化一个类时,这个$loader就去根据四种规范找该文件的绝对路径,如果这个类还有继承或实现关系,那就递归找。

    自定义一个类文件#

    现在自己写一个类文件,当实例化的时候,然后让composer来自动加载,怎么做?

    修改composer.json文件:

    {
        "require": {
            "illuminate/container": "^5.2"
        },
        "autoload": {
            "psr-4": {
                "App\": "app/"
            }
        }
    }

    这里按照psr-4规范来,然后在项目根目录下使用命令:

    composer install

    发现autoload_psr4.php文件会多一个数组值:

    return array(
        'Illuminate\Contracts\' => array($vendorDir . '/illuminate/contracts'),
        'Illuminate\Container\' => array($vendorDir . '/illuminate/container'),
        'App\' => array($baseDir . '/app'),
    );

    然后在项目根目录下新建文件:

    // app/Test/Test.php文件
    <?php
    /**
     * Created by PhpStorm.
     * User: liuxiang
     * Date: 16/5/12
     * Time: 21:52
     */
    
    namespace AppTest;
    
    class Test
    {
        public function index()
        {
            echo "This is a custom class which will be autoload by composer
    ";
        }
    }

    在index.php文件中就可以实例化Test类并调用其对象函数了:

    require_once __DIR__.'/vendor/autoload.php';
    
    //$container = new IlluminateContainerContainer();
    //var_dump($container);
    
    $test = new AppTestTest();
    $test->index();

    终端执行输出:
    图片描述

    通过在Composer中注册下,Composer就可以帮我们找到类文件,就不需要自己各种include,只需开始一句require_once就行,真的很方便。

    One More Thing...

    配置Xdebug。强烈推荐在自己的IDE中配置Xdebug,作者使用PHPStorm,并配置了Xdebug,这会提高阅读源码的效率。具体操作流程可以谷歌文档,应该很多,Netbeans或者ZendStudio应该也有很多配置文档。如果有配置不成功的,可以在本文留言下问题,作者会尽量解答。

    PlantUML插件的安装。本文UML序列图用的是PlantUML这个插件来做的,还比较好用,推荐下。可以在PHPStorm插件库里搜UML就行,然后新建一个文件时会发现多了好几个UML选项,并且还有一个PlantUML窗口:
    图片描述
    图片描述

    关于这个PlantUML有一篇文章还挺好:Create Beautiful UML Diagrams in Minutes from the JetBrains IDE,还有它的官网(就是有各种广告):PlantUML

    总结:本文主要聊了下Composer的加载流程,并以Laravel的IlluminateContainer包为例具体说明实例化类时是如何找到其文件的,并讲述如何自定义自己的类并通过Composer来注册和加载。过两天还想结合PHP的字符串和数组这些基础知识新开篇章,到时见。

  • 相关阅读:
    PAAS平台的web应用性能测试与分析
    thrift之TTransport层的分帧传输类TFramedTransport
    thrift之TTransport层的缓存传输类TBufferedTransport和缓冲基类TBufferBase
    thrift之TTransport层的堵塞的套接字I/O传输类TSocket
    ssh证书登录(实例详解)
    [转]个性化推荐技术的十大挑战
    Github上最全的APICloud开源前端框架效果盘点(转)
    api.connectionType 判断当前网络技术经验
    安卓苹果获取时间戳转成本地时间
    js获取网络图片的宽和高
  • 原文地址:https://www.cnblogs.com/xiaoqian1993/p/6541992.html
Copyright © 2020-2023  润新知