thinkphp第三方类库autoload原理
2022-11-24 11:10:29
204
{{single.collect_count}}

composer的第三方类库自动加载,其实就是将第三方类库的完整路径保存在Loader类的静态属性中,以Psr4为例

1.thinkphp\base.php

// 载入Loader类

require __DIR__ . '/library/think/Loader.php';

// 注册自动加载

Loader::register();

2.think\Loader(Loader::register())

// 注册自动加载机制

public static function register($autoload = '')

{

// 注册系统自动加载

spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);

...

self::registerComposerLoader(self::$composerPath);

注:spl_autoload_register—注册给定的函数作为 __autoload 的实现,这里是将think\\Loader::autoload注册为__autoload 的实现.

3.self::registerComposerLoader

// 注册composer自动加载

public static function registerComposerLoader($composerPath)

{

if (is_file($composerPath . 'autoload_namespaces.php')) {

$map = require $composerPath . 'autoload_namespaces.php';

foreach ($map as $namespace => $path) {

self::addPsr0($namespace, $path);

}

}

if (is_file($composerPath . 'autoload_psr4.php')) {

$map = require $composerPath . 'autoload_psr4.php';

foreach ($map as $namespace => $path) {

self::addPsr4($namespace, $path);

}

}

4.self::addPsr4

self::$prefixLengthsPsr4[$prefix[0]][$prefix] = $length;

self::$prefixDirsPsr4[$prefix] = (array) $paths;

注:到这一步,已经将第三方类库的路径存放到Loader的静态属性$prefixDirsPsr4中,下边就是use时触发的加载第三方类库

5.think\\Loader::autoload

// 自动加载

public static function autoload($class)

{

if (isset(self::$classAlias[$class])) {

return class_alias(self::$classAlias[$class], $class);

}

if ($file = self::findFile($class)) {

// Win环境严格区分大小写

if (strpos(PHP_OS, 'WIN') !== false && pathinfo($file, PATHINFO_FILENAME) != pathinfo(realpath($file), PATHINFO_FILENAME)) {

return false;

}

//将找到的文件include进来

__include_file($file);

return true;

}

}

6.findFile(前面第4步已经将类库的路径存放在$prefixDirsPsr4中)

private static function findFile($class)

{

if (!empty(self::$classMap[$class])) {

// 类库映射

return self::$classMap[$class];

}

// 查找 PSR-4

$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php';

$first = $class[0];

if (isset(self::$prefixLengthsPsr4[$first])) {

foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) {

if (0 === strpos($class, $prefix)) {

foreach (self::$prefixDirsPsr4[$prefix] as $dir) {

if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {

return $file;

}

}

}

}

}

简单整理到这里~

回帖
全部回帖({{commentCount}})
{{item.user.nickname}} {{item.user.group_title}} {{item.friend_time}}
{{item.content}}
{{item.comment_content_show ? '取消' : '回复'}} 删除
回帖
{{reply.user.nickname}} {{reply.user.group_title}} {{reply.friend_time}}
{{reply.content}}
{{reply.comment_content_show ? '取消' : '回复'}} 删除
回帖
收起
没有更多啦~
{{commentLoading ? '加载中...' : '查看更多评论'}}