一、全局安装

curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

https://docs.phpcomposer.com/00-intro.html

二、代码

require_once './vendor/autoload.php';

一、autoload.php
   加载 composer/autoload_real.php 调用 autoload_real.php 下的 getLoader() 方法
  
二、autoload_real.php
getLoader() 方法
创建 composer\ClassLoader.php 的对象 $loader 1、静态调用 $useStaticLoader
加载 composer\autoload_static.php
回调 autoload_static.php 下的 getInitializer($loader) 方法 getInitializer() 方法
通过匿名函数绑定,为$loader 对象下的私有属性赋值
$prefixLengthsPsr4,
$prefixDirsPsr4,
$prefixDirsPsr4,
$classMap 注册自动加载 $loader->register(true); spl_autoload_register([$this, 'loadClass', true, $prepend]); function loadClass($class) {
if ($file = $this->findFile($class)) {
includeFile($file)
return true;
}
}      // ClassLoader.php 下的方法
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;
} function includeFile($file)
{
include $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;
} 2、非静态调用
call_user_func(\Composer\Autoload\ComposerStaticInitd16dd22c4a12ecb92b3a245dff71e1fc::getInitializer($loader));

public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitd16dd22c4a12ecb92b3a245dff71e1fc::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitd16dd22c4a12ecb92b3a245dff71e1fc::$prefixDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInitd16dd22c4a12ecb92b3a245dff71e1fc::$prefixesPsr0;
$loader->classMap = ComposerStaticInitd16dd22c4a12ecb92b3a245dff71e1fc::$classMap; }, null, ClassLoader::class);
} 解读:
call_user_func+Closure::bind()的模式,其实这里我们也可以完全按照常规的做法,引入一个配置文件的方式来实现,Closure::bind()返回一个Closure对象,即一个闭包函数,其中一共有三个参数: closure:需要绑定的匿名函数 newthis:需要绑定到匿名函数的对象,或者 NULL 创建未绑定的闭包 newscope:想要绑定给闭包的类作用域,或者 'static' 表示不改变。如果传入一个对象,则使用这个对象的类型名。 第一个参数好理解,第二个和第三个可以配合起来使用,当我们需要在闭包函数中使用$this的时候,我们需要给这个闭包绑定一个对象,如果闭包中使用了$this,那么newthis需要指定一个对应的对象;如果修改的属性是protected或者private,那么第三个参数不能忽略,指定为这个类。 例1: class A{
public $name;
protected $age;
}
$a = new A();
$new_a = Closure::bind(function(){
$this->name = 'nine';
} , null);
$new_a();
var_dump($new_a , $a);
此时会报错Using $this when not in object context in ...,说明这个上下文并没有指定$this。 例2: class A{
public $name;
protected $age;
}
$a = new A();
$new_a = Closure::bind(function(){
$this->name = 'nine';
$this->age = 10;
} , $a);
$new_a();
var_dump($new_a , $a);
此时会报错Cannot access protected property A::$age in...,属性是受保护的。 例3: class A{
public $name;
protected $age;
}
$a = new A();
$new_a = Closure::bind(function(){
$this->name = 'nine';
$this->age = 10;
} , $a , A::class);
$new_a();
var_dump($new_a , $a);
设置成功。
 

Composer 的autoload 实现的更多相关文章

  1. Composer的Autoload源码实现2——注册与运行

    前言 上一篇 文章我们讲到了 Composer 自动加载功能的启动与初始化,经过启动与初始化,自动加载核心类对象已经获得了顶级命名空间与相应目录的映射,换句话说,如果有命名空间 'App\Consol ...

  2. Composer的Autoload源码实现1——启动与初始化

    前言 上一篇文章,我们讨论了 PHP 的自动加载原理.PHP 的命名空间.PHP 的 PSR0 与 PSR4 标准,有了这些知识,其实我们就可以按照 PSR4 标准写出可以自动加载的程序了.然而我们为 ...

  3. composer的autoload来自动加载自己编写的函数库与类库?

    1.使用命令composer init生成composer.json文件,并编辑autoload选项内容如下: 其中又包含主要的两个选项: files 和 psr-4. files就是需要compos ...

  4. 如何让Composer的autoload支持自定义文件后缀名

    PHP的Composer工具规范了我们对系统各种资源库的加载格式,借助于PHP的自动加载机制,可以很大程度上简化在应用开发过程中的类库文件引用场景.但到目前为止,它有个不是问题的问题,就是文件后缀名只 ...

  5. composer设置autoload自己的代码

    "autoload": { "psr-4": {"": ["App/base", "App/src/contr ...

  6. composer的自动加载机制(autoload)

    composer的出现真是让人们眼前一亮,web开发从此变成了一件很『好玩』的事情,开发一个CMS就像在搭积木,从packagist中取出『积木』搭建在自己的代码中,一点一点搭建出一个属于自己的王国. ...

  7. Laravel Composer and ServiceProvider

    Composer and: 创建自定义类库时,按命名空间把文件夹结构组织好 composer.json>autoload>classmap>psr-4 composer dump-a ...

  8. Composer概述及其自动加载探秘

    composer概述 一开始,最吸引我的当属 Composer 了,因为之前从没用过 Composer . Composer 是PHP中用来管理依赖关系的工具,你只需在自己的项目中声明所依赖的外部工具 ...

  9. composer 自动加载原理

    核心当然是php5加入来的_autoload函数,当实例化一个不存在的类时,在报错之前,如果定义了_autoload函数,会进行调用此函数,此函数就可以执行相关的include操作. <?php ...

随机推荐

  1. linux内核中的cfq输入输出调度算法

    1. 全称是什么? 完全公平调度算法(completely fair queuing) 2. 原理是怎样的? 先按照输入输出请求的地址进行排序,然后按排好的次序执行请求 3. 适用场景 适用于旋转式磁 ...

  2. 再谈fedora下的音乐和视频播放器的安装

    rpm包就相当于windows下的exe,已经是编译后的二进制代码,可以使用rpm命令或dnf install ???.rpm来安装 lnux下软件的安装跟windows不同, 后者要到处去找, 要做 ...

  3. golang解析json配置文件

    安装 go get github.com/akkuman/parseConfig 使用说明 环境假设 . ├── config.go ├── config.json config.json内容 { & ...

  4. P2221 [HAOI2012]高速公路

    思路 考虑每一条边的贡献,然后推式子 \[ \begin{align}&\sum_{i}V_i\times(R-i+1)\times(i-L+1)\\=&\sum_{i}V_i\lef ...

  5. p1110 报表统计(FHQ-TREAP/TREAP)

    平衡树的裸题,操作都相当简单 写了一个FHQ,但是奈何常数太大,实在过不去 最后写了一个Treap开O2水过 TREAP代码 #include <cstdio> #include < ...

  6. ETCD应用

    etcd:从应用场景到实现原理的全方位解读 ETCD:A highly-available key value store for shared configuration and service d ...

  7. 2nd,Python基础2——02

    1 列表.元组操作 列表可以对数据实现最方便的存储.修改等操作 names = ['Jack', 'Leon','Eric'] 通过下表访问列表中的元素,下标从0开始计数 names = ['Jack ...

  8. QT移植无法启动 This application failed to start because it could not find or load the QT platform

    QT配置好在自己机器上可以运行,但在别人机器上一直弹出 "This application failed to start because it could not find or load ...

  9. C+++string类如何判断字符串为空

    string类是C++STL类之一,有很丰富的接口,判断string为空是经常用到的操作. string类为空,实际也就是元素为0个. 可以按照如下方式判断: 1.string类有自己的成员函数emp ...

  10. VR外包公司—2016中国VR开发者论坛第一期

    由VR界网和暴风魔镜联合举办的2016中国VR开发者论坛第一期已于3月2日下午5点在吉林动画学院圆满落幕,本次论坛云集了VR相关领域的精英,邀请了VR社交<极乐王国>.暴风魔镜.南京睿悦. ...