我们调用一个类方法时,一定要先把这个类所在的php文件include(require)进来,然后才能调用。

我们先来看初始化文件init.php:

<?php
/*** 统一初始化*/// 定义项目路径
defined('API_ROOT') || define('API_ROOT', dirname(__FILE__) . '/..');// 引入composer
require_once API_ROOT . '/vendor/autoload.php';// 时区设置
date_default_timezone_set('Asia/Shanghai');// 引入DI服务
include API_ROOT . '/config/di.php';

di.php文件执行基本类的注入操作,在这里面会new相关的基础类。在new之前肯定要先include类所在的php文件,所以在di.php之前先包含了autoload.php作自动加载。autoload.php主体代码如下:

    public static function getLoader(){call_user_func(
\Composer\Autoload\ComposerStaticInit6835957bc29912b8a4cd2dd758af2e80::getInitializer($loader)
);$loader->register(true);return $loader;}

第一步getInitializer方法是把框架整体目录在系统中的位置以映射方法注入到加载类的属性中。我们来看这个getInitializer方法:

    public static function getInitializer(ClassLoader $loader){return \Closure::bind(function () use ($loader) {$loader->prefixLengthsPsr4 = ComposerStaticInit6835957bc29912b8a4cd2dd758af2e80::$prefixLengthsPsr4;$loader->prefixDirsPsr4 = ComposerStaticInit6835957bc29912b8a4cd2dd758af2e80::$prefixDirsPsr4;}, null, ClassLoader::class);}

通过\Closure::bind把ComposerStaticInit6835957bc29912b8a4cd2dd758af2e80的两个属性指定到加载类的对应属性。这两个属性如下:

    public static $prefixLengthsPsr4 = array ('P' => array ('Phalapi\\Auth\\' => 13,'PhalApi\\Task\\' => 13,'PhalApi\\Redis\\' => 14,'PhalApi\\QrCode\\' => 15,'PhalApi\\PHPMailer\\' => 18,'PhalApi\\NotORM\\' => 15,'PhalApi\\CLI\\' => 12,'PhalApi\\' => 8,'PHPMailer\\PHPMailer\\' => 20,),'M' => array ('Medoo\\' => 6,),'A' => array ('App\\' => 4,),);public static $prefixDirsPsr4 = array ('Phalapi\\Auth\\' => array (0 => __DIR__ . '/..' . '/phalapi/auth/src',),'PhalApi\\Task\\' => array (0 => __DIR__ . '/..' . '/phalapi/task/src',),'PhalApi\\Redis\\' => array (0 => __DIR__ . '/..' . '/phalapi/redis/src',),'PhalApi\\QrCode\\' => array (0 => __DIR__ . '/..' . '/phalapi/qrcode/src',),'PhalApi\\PHPMailer\\' => array (0 => __DIR__ . '/..' . '/phalapi/phpmailer/src',),'PhalApi\\NotORM\\' => array (0 => __DIR__ . '/..' . '/phalapi/notorm/src',),'PhalApi\\CLI\\' => array (0 => __DIR__ . '/..' . '/phalapi/cli/src',),'PhalApi\\' => array (0 => __DIR__ . '/..' . '/phalapi/kernal/src',),'PHPMailer\\PHPMailer\\' => array (0 => __DIR__ . '/..' . '/phpmailer/phpmailer/src',),'Medoo\\' => array (0 => __DIR__ . '/..' . '/catfan/medoo/src',),'App\\' => array (0 => __DIR__ . '/../..' . '/src/app',),);

框架的所有主体目录都在这里了。然后我们再来看$loader->register(true);执行了什么操作:

    public function register($prepend = false){spl_autoload_register(array($this, 'loadClass'), true, $prepend);}public function loadClass($class){if ($file = $this->findFile($class)) {includeFile($file);return true;}}
我们看到,register主要是把loadClass方法注册为类的自动加载器。
当我们调用一个类时,他会通过这个方法自动加载。
我们看到,loadClass里主要执行了两步操作,先找到文件,然后再include进来

简单点,先看includeFile方法:

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 dirsforeach ($this->fallbackDirsPsr4 as $dir) {if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {return $file;}}// PSR-0 lookupif (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 dirsforeach ($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;}

主要是这个方法,可以看到,是从之前绑定到loadClass类中的两个保存框架所有主体目录的属性里(映射),搜索出被调用类的实际所以目录,然后跟传入的带有命令空间类一组装,就是类所在php文件。然后判断文件存在时,返回文件路径,方法通过include引用.

比如:
$this->model = new \App\Model\GroupUser();
自动加载时就会根据这个类路径(App\Model\GroupUser)去之前定义的框架基本目录映射所在的两个loadClas属性去去找,目录范围由小往大的找,比如这里,属性里有App索引对应的值,但是没有App\Model目录对应的值,先找App\Model目录在索引列表里没有,这里没有找到,所以就直接找App目录.这里找到'App\\' => array (0 => __DIR__ . '/../..' . '/src/app',),这一项(其实是先根据首字母去第一个映射属性里找:        'A' => array ('App\\' => 4,),判断对应的路径是否存在)
然后取出值:__DIR__ . '/../..' . '/src/app',去掉重复的路径app,所以就剩下\Model\GroupUser.php然后判断:if (file_exists($file = $dir . $pathEnd)) {return $file;}
这样就索引到类文件了.当然这是在类的namespace完全遵从目录结构来的。有正面一种情况,当我定义一个类,同样是$this->model = new \App\Model\EroupUser();但其实我的EroupUser.php文件是放在 Model下的Task目录.这样上面就索引不到.
src\app\Model\EroupUser.php文件肯定是不存在的。看我的错误日记:
2019-11-01 15:25:50|ERROR|App.Home_Site.Test|Error: Class 'App\Model\EroupUser' not found in D:\home\www\ecsapi\src\app\Api\Home\Site.php:132

2.自动加载(phalapi框架总结)相关推荐

  1. phpexcel的自动加载与其他框架有冲突

    2019独角兽企业重金招聘Python工程师标准>>> 一直想用phpEXCEL,这次这个项目遇到了.然而坑也出来了.phpexcel的Autoloader.php里面 public ...

  2. thinkphp 框架自动加载原理_ThinkPHP5分析Part 1 基本框架流程

    ThinkPHP是一个免费开源的,快速.简单的面向对象的轻量级PHP开发框架,是为了敏捷WEB应用开发和简化企业应用开发而诞生的.ThinkPHP从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能 ...

  3. php ci框架 实例化类,php框架CI(codeigniter)自动加载与自主创建对象操作实例分析...

    本文实例讲述了php框架CI(codeigniter)自动加载与自主创建对象操作.分享给大家供大家参考,具体如下: CI的autoload很好用,自动创建对象,但是注意,他的对象只有一个. 我们很多情 ...

  4. thinkphp 框架自动加载原理_这下你应该理解ThinkPHP的Loader自动加载了

    想了很久终于要开始系列文章的编写了,期望是写出提升和面试都可以搞定的系列文章. 当你看到本文时,如果你发现咔咔没有编写到的面试热点问题或者技术难点,期待评论区指出,一起完善. 前言 目前再整理PHP进 ...

  5. PHP框架自动加载类文件原理

    描述:公司项目PHP用作中间转发层(接收http请求,用 socket跟c++做通信),由于代码没有用到框架,这些东西自然就是之前的人自己写的.最近需要对这个底层进行优化,于是便看了下这部分的代码. ...

  6. thinkphp 框架自动加载原理_thinkPHP5.0框架自动加载机制分析

    本文实例讲述了thinkPHP5.0框架自动加载机制.分享给大家供大家参考,具体如下: 概述 ThinkPHP5.0 真正实现了按需加载,所有类库采用自动加载机制,并且支持类库映射和composer类 ...

  7. phalapi-进阶篇3(自动加载和拦截器)

    phalapi-进阶篇3(自动加载和拦截器) 前言 先在这里感谢phalapi框架创始人@dogstar,为我们提供了这样一个优秀的开源框架. 最近工作上事情比较多所以更新比较慢希望大家见谅!这一次带 ...

  8. php的_autoload函数实现自动加载类的使用

    本文章详细的以实例来介绍了关于php _autoload自动加载类的用法以及如何使用_autoload来减少程序上的include和require的调用哦. 在使用PHP的OO模式开发系统时,通常大家 ...

  9. php自动加载类与路由,PHP实现路由与类自动加载步骤详解

    这次给大家带来PHP实现路由与类自动加载步骤详解,PHP实现路由与类自动加载步骤详解的注意事项有哪些,下面就是实战案例,一起来看一下. 项目目录如下 入口文件index.php<?php def ...

  10. yii2 引入php文件,Yii2中YiiBase自动加载类、引用文件方法分析(autoload)

    本文实例分析了Yii2中YiiBase自动加载类.引用文件的方法.分享给大家供大家参考,具体如下: 在Yii2中这个函数是用来加载类的,没有直接引用文件的相关实现.但是这个也可以用来引用文件. pub ...

最新文章

  1. FlashDevelop Android开发.md
  2. Javascript基础与面向对象基础~第六讲 Javascript中的事件机制
  3. AI说,它可以把你变成个游戏 | 3D人体模型 · CVPR
  4. 广播接收者android,电话拦截广播,电话接收者demo
  5. WPF剪切板问题-OpenClipboard HRESULT:0x800401D0 (CLIPBRD_E_CANT_OPEN))
  6. 网页版怎么连接tcp服务器,请教怎么做一个tcp客户端访问网页
  7. idea2018破解有效期至2100年
  8. Linux(1) 概要、安装 、文件系统基本认知
  9. 怎么在微软官网找到visual studio历史版本
  10. 穷到低谷时的创业时间表
  11. dnf剑魂buff等级上限_DNF:半年前没人看得上,如今被开发成T0,这神话终于翻身了...
  12. Vue完成数据请求后内容超出显示省略号+显示查看全文按钮
  13. Android 系统级别广播
  14. 红黑树的创建、插入节点
  15. HTTP响应是什么?
  16. arm 关于m a r系列区别
  17. 必应每日壁纸图片API
  18. OO六大设计原则最全分析总结篇
  19. c#中使用Aspose.Word组件,将数据和图片导出至Word
  20. 基于AI+视频智能分析技术的SkeyeVSS建筑废弃物监管解决方案

热门文章

  1. Python脚本系列:拳皇13一键出招以及连段实现!谁打得过我?
  2. 再次哀悼吧!最佳夸浏览器同步 Xmarks 宣布终止服务
  3. Android 适配器 自定义
  4. 保留数据和程序win7升级win10,平滑升级,完美!
  5. 软件开发模型优缺点及其适用范围
  6. 看你知道多少种水凝胶的改性及其分类
  7. python seo快排_流量贩子GoGo闯:SEO黑帽点击快排发包+Python应用软件编程技术
  8. 【读书笔记】Flickr 网站用户标签的质量控制对策
  9. 安全防范知识点 -- CSRF
  10. 手游运营基础知识大全