Table of Contents
简介
composer 自动加载原理
Home Development Tools composer Composer implements automatic loading principle [detailed explanation]

Composer implements automatic loading principle [detailed explanation]

Jul 02, 2020 pm 01:13 PM
composer

下面由composer教程栏目给大家介绍composer实现自动加载原理,希望对需要的朋友有所帮助!

Composer implements automatic loading principle [detailed explanation]

简介

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

composer 自动加载原理

以在Laravel框架中为例:

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

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

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

    <?php
    
    // autoload_real.php @generated by Composer
    
    class ComposerAutoloaderInit1215780529014c2b50a6fca7ce889273
    {
        private static $loader;
    
        public static function loadClassLoader($class)
        {
            if (&#39;Composer\Autoload\ClassLoader&#39; === $class) {
                require __DIR__ . &#39;/ClassLoader.php&#39;;
            }
        }
    
        public static function getLoader()
        {
            if (null !== self::$loader) {
                return self::$loader;
            }
            spl_autoload_register(array(&#39;ComposerAutoloaderInit1215780529014c2b50a6fca7ce889273&#39;, &#39;loadClassLoader&#39;), true, true);
            self::$loader = $loader = new \Composer\Autoload\ClassLoader();
            spl_autoload_unregister(array(&#39;ComposerAutoloaderInit1215780529014c2b50a6fca7ce889273&#39;, &#39;loadClassLoader&#39;));
    
            $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined(&#39;HHVM_VERSION&#39;) && (!function_exists(&#39;zend_loader_file_encoded&#39;) || !zend_loader_file_encoded());
            if ($useStaticLoader) {
                require_once __DIR__ . &#39;/autoload_static.php&#39;;
    
                call_user_func(\Composer\Autoload\ComposerStaticInit1215780529014c2b50a6fca7ce889273::getInitializer($loader));
            } else {
                $map = require __DIR__ . &#39;/autoload_namespaces.php&#39;;
                foreach ($map as $namespace => $path) {
                    $loader->set($namespace, $path);
                }
    
                $map = require __DIR__ . &#39;/autoload_psr4.php&#39;;
                foreach ($map as $namespace => $path) {
                    $loader->setPsr4($namespace, $path);
                }
    
                $classMap = require __DIR__ . &#39;/autoload_classmap.php&#39;;
                if ($classMap) {
                    $loader->addClassMap($classMap);
                }
            }
    
            $loader->register(true);
    
            if ($useStaticLoader) {
                $includeFiles = Composer\Autoload\ComposerStaticInit1215780529014c2b50a6fca7ce889273::$files;
            } else {
                $includeFiles = require __DIR__ . &#39;/autoload_files.php&#39;;
            }
            foreach ($includeFiles as $fileIdentifier => $file) {
                composerRequire1215780529014c2b50a6fca7ce889273($fileIdentifier, $file);
            }
    
            return $loader;
        }
    }
    
    function composerRequire1215780529014c2b50a6fca7ce889273($fileIdentifier, $file)
    {
        if (empty($GLOBALS[&#39;__composer_autoload_files&#39;][$fileIdentifier])) {
            require $file;
    
            $GLOBALS[&#39;__composer_autoload_files&#39;][$fileIdentifier] = true;
        }
    }
    Copy after login

可以看出这一段是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, &#39;.php&#39;);
    
            // Search for Hack files if we are running on HHVM
            if (false === $file && defined(&#39;HHVM_VERSION&#39;)) {
                $file = $this->findFileWithExtension($class, &#39;.hh&#39;);
            }
    
            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, &#39;\\&#39;, DIRECTORY_SEPARATOR) . $ext;
    
            $first = $class[0];
            if (isset($this->prefixLengthsPsr4[$first])) {
                $subPath = $class;
                while (false !== $lastPos = strrpos($subPath, &#39;\\&#39;)) {
                    $subPath = substr($subPath, 0, $lastPos);
                    $search = $subPath.&#39;\\&#39;;
                    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, &#39;\\&#39;)) {
                // namespaced class name
                $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
                    . strtr(substr($logicalPathPsr4, $pos + 1), &#39;_&#39;, DIRECTORY_SEPARATOR);
            } else {
                // PEAR-like class name
                $logicalPathPsr0 = strtr($class, &#39;_&#39;, 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;
        }
    Copy after login

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

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

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

    1. spl_autoload_register函数
      spl_autoload_register — 注册给定的函数作为 __autoload 的实现,
      1. bool spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] )

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

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

        function __autoload($name)
        {
            require &#39;class/&#39;.$name.&#39;.php&#39;;
            echo &#39;1&#39;;
        }
        function autoload_test($name)
        {
            echo &#39;2&#39;;
        }
        spl_autoload_register(&#39;autoload_test&#39;);
        spl_autoload_register(&#39;__autoload&#39;);
        $ca=new Ca();
        Copy after login
    2. spl_autoload_unregister函数
      spl_autoload_unregister — 注销已注册的__autoload()函数,如果该函数队列处于激活状态,并且在给定函数注销后该队列变为空,则该函数队列将会变为无效。如果该函数注销后使得自动装载函数队列无效,即使存在有__autoload函数它也不会自动激活。
      1. bool spl_autoload_unregister ( mixed $autoload_function )
    3. 因本人水平有限,有些地方可能不对,欢迎留言。

      The above is the detailed content of Composer implements automatic loading principle [detailed explanation]. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: How To Unlock Everything In MyRise
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Composer's advanced features: aliases, scripts, and conflict resolution Composer's advanced features: aliases, scripts, and conflict resolution Jun 03, 2024 pm 12:37 PM

Composer provides advanced features, including: 1. Aliases: define convenient names for packages for repeated reference; 2. Scripts: execute custom commands when installing/updating packages, used to create database tables or compile resources; 3. Conflict resolution: use priorities Rules, satisfaction constraints, and package aliases resolve the different requirements of multiple packages for the same dependency version to avoid installation conflicts.

Agile development and operation of PHP microservice containerization Agile development and operation of PHP microservice containerization May 08, 2024 pm 02:21 PM

Answer: PHP microservices are deployed with HelmCharts for agile development and containerized with DockerContainer for isolation and scalability. Detailed description: Use HelmCharts to automatically deploy PHP microservices to achieve agile development. Docker images allow for rapid iteration and version control of microservices. The DockerContainer standard isolates microservices, and Kubernetes manages the availability and scalability of the containers. Use Prometheus and Grafana to monitor microservice performance and health, and create alarms and automatic repair mechanisms.

What are the common ways to convert arrays to objects in PHP? What are the common ways to convert arrays to objects in PHP? Apr 28, 2024 pm 10:54 PM

How to convert PHP array to object: use stdClass class, use json_decode() function, use third-party library (such as ArrayObject class, Hydrator library)

PHP code version control and collaboration PHP code version control and collaboration May 07, 2024 am 08:54 AM

PHP code version control: There are two version control systems (VCS) commonly used in PHP development: Git: distributed VCS, where developers store copies of the code base locally to facilitate collaboration and offline work. Subversion: Centralized VCS, a unique copy of the code base is stored on a central server, providing more control. VCS helps teams track changes, collaborate and roll back to earlier versions.

The role of PHP CI/CD in DevOps projects The role of PHP CI/CD in DevOps projects May 08, 2024 pm 09:09 PM

PHPCI/CD is a key practice in DevOps projects that automates the build, test, and deployment processes to improve development efficiency and software quality. A typical PHPCI/CD pipeline consists of the following stages: 1) Continuous Integration: Whenever the code changes, the code is automatically built and tested. 2) Continuous deployment: Speed ​​up delivery by automatically deploying tested and integrated code to the production environment. By implementing the PHPCI/CD pipeline, you can increase development efficiency, improve software quality, shorten time to market, and improve reliability.

How to use Redis cache in PHP array pagination? How to use Redis cache in PHP array pagination? May 01, 2024 am 10:48 AM

Using Redis cache can greatly optimize the performance of PHP array paging. This can be achieved through the following steps: Install the Redis client. Connect to the Redis server. Create cache data and store each page of data into a Redis hash with the key "page:{page_number}". Get data from cache and avoid expensive operations on large arrays.

Visualization technology of PHP data structure Visualization technology of PHP data structure May 07, 2024 pm 06:06 PM

There are three main technologies for visualizing data structures in PHP: Graphviz: an open source tool that can create graphical representations such as charts, directed acyclic graphs, and decision trees. D3.js: JavaScript library for creating interactive, data-driven visualizations, generating HTML and data from PHP, and then visualizing it on the client side using D3.js. ASCIIFlow: A library for creating textual representation of data flow diagrams, suitable for visualization of processes and algorithms.

How to use PHP CI/CD to iterate quickly? How to use PHP CI/CD to iterate quickly? May 08, 2024 pm 10:15 PM

Answer: Use PHPCI/CD to achieve rapid iteration, including setting up CI/CD pipelines, automated testing and deployment processes. Set up a CI/CD pipeline: Select a CI/CD tool, configure the code repository, and define the build pipeline. Automated testing: Write unit and integration tests and use testing frameworks to simplify testing. Practical case: Using TravisCI: install TravisCI, define the pipeline, enable the pipeline, and view the results. Implement continuous delivery: select deployment tools, define deployment pipelines, and automate deployment. Benefits: Improve development efficiency, reduce errors, and shorten delivery time.

See all articles