Analyze the principle of automatic loading of composer

Time:2022-6-17
catalogue
  • 1. entry file
  • 2.  autoload.php
  • 3. autoload_real.php
  • 5. spl_ autoload_ Register and SPL_ autoload_ Unregister function
    • 1. spl_ autoload_ Register function
    • 2. spl_ autoload_ Unregister function

1. entry file

(/public/index.php) introduces autoload php

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

2.  autoload.php

require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit1215780529014c2b50a6fca7ce889273::getLoader();

3. autoload_real.php


<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit1215780529014c2b50a6fca7ce889273{
    private static $loader;
    public static function loadClassLoader($class){
        if ('Composer\Autoload\ClassLoader' === $class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }
    public static function getLoader(){
        if (null !== self::$loader) {
            return self::$loader;
        }
        spl_autoload_register(array('ComposerAutoloaderInit1215780529014c2b50a6fca7ce889273', 'loadClassLoader'), true, true);
        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
        spl_autoload_unregister(array('ComposerAutoloaderInit1215780529014c2b50a6fca7ce889273', 'loadClassLoader'));
        $useStaticLoader = PHP_VERSION_ID >= 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;
    }
}
 

It can be seen that this section is the focus of composer automatic loading. First, in autoload Called in PHP

Composerautoloaderininit1215780529014c2b50a6fca7ce889273:: getloader() method. Getloader() first determines whether the current loader is null. If it is not null, it returns directly. Otherwise, it initializes a classloader class to assign a value to the loader. If it is not null, it returns directly. Otherwise, it initializes a classloader class to assign a value to the loader, and then autoload_ namespaces. php、autoload_ psr4.php、autoload_ classmap. Add the contents of the PHP file to the corresponding array in $loader, and then register the loadclass function to autoload_ files. All the files shown in the path in PHP are included. When a new class is created, if no relevant class is found, this loadclass function will be triggered. Loadclass() calls findfile() to find the corresponding file. After finding the corresponding file, the file will be returned. Then loadclass calls the includefile() method to include the file. Otherwise, findfile returns false, This completes the automatic loading

4.  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;
}

The findfile() function searches the classmap first. If it cannot be found, it will try to find it in the APCU cache. If it still cannot be found, it will call the findfilewithextension() function to find it. If it is found, it will add the file to the APCU cache, If it cannot be found, a mark will be set in the missingclasses array to identify that the class cannot be found. The findfilewithextension() method finds the path information of the class file according to the information previously set through the loader->set (loader − >set (namespace, path) and path) and loader->setpsr4 (namespace, namespace, path) methods

5. spl_ autoload_ Register and SPL_ autoload_ Unregister function

1. spl_ autoload_ Register function

1.spl_ autoload_ Register – registers the given function as__ The implementation of autoload,

bool spl_autoload_register([callable autoloadfunction[,boolautoloadfunction[,boolthrow = true [, bool $prepend = false ]]])

2.prepend

If true, SPL_ autoload_ Register () adds a function to the head of the queue, not the tail.

3. if you have implemented the autoload() function in your program, it must be explicitly registered in the autoload() queue. Because SPL_ autoload_ The register() function will__ Autoload() function replaced with SPL_ Autoload() or SPL_ autoload_ call ()

Example:

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();

2. spl_ autoload_ Unregister function

spl_ autoload_ Unregister – unregisters the registered autoload() function. If the function queue is active and becomes empty after the given function is unregistered, the function queue will become invalid. If the autoload function queue is invalid after the function is logged off, it will not be activated automatically even if the autoload function exists.

bool spl_autoload_unregister ( mixed $autoload_function )

The above is the detailed content of analyzing the principle of automatic loading of composer. For more information about the principle of automatic loading of composer, please pay attention to other relevant developeppaer articles!

Recommended Today

An article teaches you how to check Net memory leak

catalogue preface Check managed memory usage Generate dump file Analyze core dump summary preface Memory leakage usually means that after an application completes its life cycle, some objects are accidentally referenced by other objects, resulting in subsequent GC failure to recycle them. In the long run, it will lead to program performance degradation and potential […]