千家信息网

composer实现自动加载原理的方法

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,小编给大家分享一下composer实现自动加载原理的方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!简介一般在框架中都会
千家信息网最后更新 2026年11月04日composer实现自动加载原理的方法

小编给大家分享一下composer实现自动加载原理的方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

简介

一般在框架中都会用到composer工具,用它来管理依赖。其中composer有类的自动加载机制,可以加载composer下载的库中的所有的类文件。那么composer的自动加载机制是怎么实现的呢?

composer 自动加载原理

以在Laravel框架中为例:

  1. 首先在入口文件(/public/index.php)中引入了autoload.php

    require __DIR__.'/../vendor/autoload.php';
  2. 我们看看autoload.php的内容

    require_once __DIR__ . '/composer/autoload_real.php';return ComposerAutoloaderInit1215780529014c2b50a6fca7ce889273::getLoader();
  3. 我们再看看 autoload_real.php的内容

    = 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());        if ($useStaticLoader) {            require_once __DIR__ . '/autoload_static.php';            call_user_func(\Composer\Autoload\ComposerStaticInit1215780529014c2b50a6fca7ce889273::getInitializer($loader));        } else {            $map = require __DIR__ . '/autoload_namespaces.php';            foreach ($map as $namespace => $path) {                $loader->set($namespace, $path);            }            $map = require __DIR__ . '/autoload_psr4.php';            foreach ($map as $namespace => $path) {                $loader->setPsr4($namespace, $path);            }            $classMap = require __DIR__ . '/autoload_classmap.php';            if ($classMap) {                $loader->addClassMap($classMap);            }        }        $loader->register(true);        if ($useStaticLoader) {            $includeFiles = Composer\Autoload\ComposerStaticInit1215780529014c2b50a6fca7ce889273::$files;        } else {            $includeFiles = require __DIR__ . '/autoload_files.php';        }        foreach ($includeFiles as $fileIdentifier => $file) {            composerRequire1215780529014c2b50a6fca7ce889273($fileIdentifier, $file);        }        return $loader;    }}function composerRequire1215780529014c2b50a6fca7ce889273($fileIdentifier, $file){    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {        require $file;        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;    }}

可以看出这一段是composer自动加载的重点,首先在 autoload.php中调用ComposerAutoloaderInit1215780529014c2b50a6fca7ce889273::getLoader()方法,getLoader()首先判断当前\(loader是不是null,如果不为null就直接返回,否则就初始化一个ClassLoader类给赋值给\)loader,接着将autoload_namespaces.php、autoload_psr4.php、autoload_classmap.php文件中的内容加入到$loader中对应的数组中,然后给注册loadClass函数,将autoload_files.php中的所有路径所示的文件都包含进来,当在new一个类的时候如果没有找到相关的类就会触发这个loadClass函数,在loadClass()又调用了findFile()去查找相应的文件,找到相应文件后就会返回该文件,然后loadClass调用includeFile()方法将该文件include进去,否则findFile返回false,这样就完成了自动加载

  1. 下面来看一下 findFile()

     public function findFile($class)    {        // class map lookup        if (isset($this->classMap[$class])) {            return $this->classMap[$class];        }        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {            return false;        }        if (null !== $this->apcuPrefix) {            $file = apcu_fetch($this->apcuPrefix.$class, $hit);            if ($hit) {                return $file;            }        }        $file = $this->findFileWithExtension($class, '.php');        // Search for Hack files if we are running on HHVM        if (false === $file && defined('HHVM_VERSION')) {            $file = $this->findFileWithExtension($class, '.hh');        }        if (null !== $this->apcuPrefix) {            apcu_add($this->apcuPrefix.$class, $file);        }        if (false === $file) {            // Remember that this class does not exist.            $this->missingClasses[$class] = true;        }        return $file;    }     private function findFileWithExtension($class, $ext)    {        // PSR-4 lookup        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;        $first = $class[0];        if (isset($this->prefixLengthsPsr4[$first])) {            $subPath = $class;            while (false !== $lastPos = strrpos($subPath, '\\')) {                $subPath = substr($subPath, 0, $lastPos);                $search = $subPath.'\\';                if (isset($this->prefixDirsPsr4[$search])) {                    $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);                    foreach ($this->prefixDirsPsr4[$search] as $dir) {                        if (file_exists($file = $dir . $pathEnd)) {                            return $file;                        }                    }                }            }        }        // PSR-4 fallback dirs        foreach ($this->fallbackDirsPsr4 as $dir) {            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {                return $file;            }        }        // PSR-0 lookup        if (false !== $pos = strrpos($class, '\\')) {            // namespaced class name            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);        } else {            // PEAR-like class name            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;        }        if (isset($this->prefixesPsr0[$first])) {            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {                if (0 === strpos($class, $prefix)) {                    foreach ($dirs as $dir) {                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {                            return $file;                        }                    }                }            }        }        // PSR-0 fallback dirs        foreach ($this->fallbackDirsPsr0 as $dir) {            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {                return $file;            }        }        // PSR-0 include paths.        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {            return $file;        }        return false;    }

    findFile()函数先在classMap中查找,如果找不到的话就会尝试在apcu缓存中查找,如果还是找不到的话就会调用findFileWithExtension()函数查找,如果找到了就会将该文件加到apcu缓存,如果找不到的话就会在missingClasses数组中设一个标记表示识这个类找不到

    findFileWithExtension()方法根据之前通过\(loader->set(\)namespace, \(path)和\)loader->setPsr4($namespace, $path)方法设置的信息找出类文件的路径信息

  2. 在上面有的地方用到了 spl_autoload_register和spl_autoload_unregister函数

    1. bool spl_autoload_unregister ( mixed $autoload_function )

    2. bool spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] )

    3. prepend
      如果是 true,spl_autoload_register() 会添加函数到队列之首,而不是队列尾部。

    4. 如果在你的程序中已经实现了__autoload()函数,它必须显式注册到__autoload()队列中。因为 spl_autoload_register()函数会将Zend Engine中的__autoload()函数取代为spl_autoload()或spl_autoload_call()
      例:

      function __autoload($name){    require 'class/'.$name.'.php';    echo '1';}function autoload_test($name){    echo '2';}spl_autoload_register('autoload_test');spl_autoload_register('__autoload');$ca=new Ca();
    5. spl_autoload_register函数
      spl_autoload_register - 注册给定的函数作为 __autoload 的实现,

    6. spl_autoload_unregister函数
      spl_autoload_unregister - 注销已注册的__autoload()函数,如果该函数队列处于激活状态,并且在给定函数注销后该队列变为空,则该函数队列将会变为无效。如果该函数注销后使得自动装载函数队列无效,即使存在有__autoload函数它也不会自动激活。

以上是"composer实现自动加载原理的方法"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

函数 文件 方法 队列 内容 原理 篇文章 信息 数组 机制 框架 激活 缓存 路径 不怎么 入口 地方 大部分 尾部 工具 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网是第几次科技革命的成果 科技互联网公司装修 关于新基建和互联网科技 新浪科技互联网 互联网 视角下的科技创新 广州紫鲸互联网科技 中国最先进互联网科技公司 华中科技有哪些互联网大佬 成都铂石互联网科技做什么的 荆州市昕露互联网络科技有限公司 互联网科技如何创业 中天科技中国工业互联网 互联网科技资金流入 厦门江牛科技互联网 半导体是互联网高科技吗 科技互联网行业投资研究 求路客互联网科技电话 上海旺乐尼互联网科技有限公司 东风日产互联网科技公司叫什么 互联网科技企业文化 互联网科技工作委员会副主任毛军 华宇互联网科技 互联网金融 科技创新 互联网养老 桔豆科技 小米互联网科技园设置 华服互联网科技官网 卓翼科技产业互联网合作 江苏互联网科技小贷 东营紫格互联网科技 江苏互联网智能科技产品出厂价
0