ThinkPHP6 源码分析之应用初始化

官方群点击此处

App Construct

先来看看在 __construct 中做了什么,基本任何框架都会在这里做一些基本的操作,也就是从这里开始延伸出去。

public function __construct(string $rootPath = '')

{

    $this->thinkPath   = dirname(__DIR__) . DIRECTORY_SEPARATOR;

    $this->rootPath    = $rootPath ? rtrim($rootPath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : $this->getDefaultRootPath();

    $this->appPath     = $this->rootPath . 'app' . DIRECTORY_SEPARATOR;

    $this->runtimePath = $this->rootPath . 'runtime' . DIRECTORY_SEPARATOR;

    if (is_file($this->appPath . 'provider.php')) {

        $this->bind(include $this->appPath . 'provider.php');

    }

    static::setInstance($this);

    $this->instance('app', $this);

    $this->instance('think\Container', $this);

}

● 从魔术的方法的参数 rootPath 来看,是支持自定义根目录路径的。

● 设置了 thinkPath, rootPath, appPath, runtimePath

● 绑定了默认的服务提供者,一共提供了两个,app\Reques 和 app\ExceptionHandle,实际上你使用的 Request 就是它。具体到 appPath 查看

● 设置当前容器实例 APP

● 将 App($this) 实例 绑定到容器中,分别是 app 和 think\Container

这里需要注意的是 App 类是继承 Container 的,所以就是将自身实例绑定到容器中。

在这里似乎整个应用就已经初始化结束了?这里我需要把一部分 Request run 的内容放在这里说,因为那里才是框架主要的初始化工作,我并不认为将这一部分初始化工作放在 Request run 中是合理的。

主要的初始化

public function initialize()

{

    $this->initialized = true;

    $this->beginTime = microtime(true);

    $this->beginMem  = memory_get_usage();

    // 加载环境变量

    if (is_file($this->rootPath . '.env')) {

        $this->env->load($this->rootPath . '.env');

    }

    $this->configExt = $this->env->get('config_ext', '.php');

    $this->debugModeInit();

    // 加载全局初始化文件

    $this->load();

    // 加载框架默认语言包

    $langSet = $this->lang->defaultLangSet();

    $this->lang->load($this->thinkPath . 'lang' . DIRECTORY_SEPARATOR . $langSet . '.php');

    // 加载应用默认语言包

    $this->loadLangPack($langSet);

    // 监听AppInit

    $this->event->trigger('AppInit');

    date_default_timezone_set($this->config->get('app.default_timezone', 'Asia/Shanghai'));

    // 初始化

    foreach ($this->initializers as $initializer) {

        $this->make($initializer)->init($this);

    }

    return $this;

}

● 加载 .env 环境变量文件

● 加载配置文件以及应用内的文件

● 加载应用内的 common.php

● 加载助手函数 在 thinkPath 目录下的 helper.php

● 加载配置文件

● 加载应用目录下的 event.php 事件

● 注册应用目录下的 service.php 服务

● 加载语言包

● 监听 AppInit 事件,利用该事件可以做一些请求前的工作

● 设置时区

● 注入所有服务并且启动服务

服务注册

初始化过程中,进行服务注册,那么服务注册做了哪些事情呢?该如何使用的服务呢?

public function register($service, bool $force = false)

{

    $registered = $this->getService($service);

    if ($registered && !$force) {

        return $registered;

    }

    if (is_string($service)) {

        $service = new $service($this);

    }

    if (method_exists($service, 'register')) {

        $service->register();

    }

    if (property_exists($service, 'bind')) {

        $this->bind($service->bind);

    }

    $this->services[] = $service;

}

● 服务是否注册过,如果需要强制重新注册

● 实例化服务

● 如果实现了 register 方法,则需要执行 register 方法

● 如果设置了 bind 属性,则需要将 service 实例绑定到容器

● 最后合并到整个 service 数组中,等待 boot

服务启动

目前在初始化的时候只有下面三个服务,在 $this->initializers 数组中

foreach ($this->initializers as $initializer) {

        $this->make($initializer)->init($this);

}

这三个服务分别是:

think\initializer\BootService

think\initializer\Error

think\initializer\RegisterService

● Error 服务是用来处理框架异常和错误的

● RegisterService 从字面的意思就是注册服务的

● BootService 就是启用服务的

Error 处理在之后再说,这里说一下 RegisterService 和 BootService。

当从 Container 中 make 出 RegisterService 的时候

这里有个隐藏的静态方法 make,每次如果首次从 Container 中 make 出来的实例对象都会执行 make 方法,当然首先必须你实现了该方法。

随后会执行 Init 方法。当你进入到 RegisterService 的时候,你会看到该方法。方法内容如下:

public function init(App $app)

{

    $file = $app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . 'services.php';

    $services = $this->services;

    if (is_file($file)) {

        $services = array_merge($services, include $file);

    }

    foreach ($services as $service) {

        if (class_exists($service)) {

            $app->register($service);

        }

    }

}

该方法就很奇怪了,和我想象的有点不一样。服务是直接从 runtime 目录下面获取的,而非在 config 目录下的 service.php 中。为什么会这样呢?由于 composer 的发展,TP 框架也可以提供包的自动发现的功能,这也证明了开发组在不断向社区靠拢。下面来看一下是如何实现的。

因为这都是得益于 composer 的,所以来看一下 rootPath 下的 composer.json,到最下面,你会发现下面的配置

"scripts": {

    "post-autoload-dump": [

        "@php think service:discover",

        "@php think vendor:publish"

    ]

}

从配置来看,框架一共提供了两个指令,service:discover 和 vendor:publish。具体实现这里就不说了,你只需要知道包的发现是由 service:discover 实现的。

还有就是这里默认注入了三个服务。

PaginatorService::class,

ValidateService::class,

ModelService::class,

最后再来看看 BootService,这个就很简单了。从命名来讲就不难看出,下面就是代码,正常的启动服务,但是这里要说明的是,服务类中必须实现了 boot 方法才会启动。

public function init(App $app)

{

    $app->boot();

}

以上就是ThinkPHP6源码分析之应用初始化的详细内容

以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的可以加入我的官方群点击此处

ThinkPHP6源码分析之应用初始化的更多相关文章

  1. Spring IOC 容器源码分析 - 余下的初始化工作

    1. 简介 本篇文章是"Spring IOC 容器源码分析"系列文章的最后一篇文章,本篇文章所分析的对象是 initializeBean 方法,该方法用于对已完成属性填充的 bea ...

  2. SDL2源码分析1:初始化(SDL_Init())

    ===================================================== SDL源码分析系列文章列表: SDL2源码分析1:初始化(SDL_Init()) SDL2源 ...

  3. Thinkphp6源码分析之解析,Thinkphp6路由,Thinkphp6路由源码解析,Thinkphp6请求流程解析,Thinkphp6源码

    Thinkphp6源码解析之分析 路由篇-请求流程 0x00 前言: 第一次写这么长的博客,所以可能排版啊,分析啊,什么的可能会比较乱.但是我大致的流程已经觉得是说的够清楚了.几乎是每行源码上都有注释 ...

  4. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

  5. Bootstrap源码分析系列之初始化和依赖项

    在上一节中我们介绍了Bootstrap整体架构,本节我们将介绍Bootstrap框架第二部分初始化及依赖项,这部分内容位于源码的第8~885行,打开源码这部分内容似乎也不是很难理解.但是请站在一个开发 ...

  6. nginx源码分析之模块初始化

    在nginx启动过程中,模块的初始化是整个启动过程中的重要部分,而且了解了模块初始化的过程对应后面具体分析各个模块会有事半功倍的效果.在我看来,分析源码来了解模块的初始化是最直接不过的了,所以下面主要 ...

  7. linux内存源码分析 - 页表的初始化

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 本文章中系统我们假设为x86下的32位系统,暂且不分析64位系统的页表结构. linux分页 linux下采用四 ...

  8. SQLmap源码分析之框架初始化(一)

    SQLmap是现在搞web人手一个的注入神器,不仅包含了主流数据库的SQL注入检测,而且包含提权以及后渗透模块.基于python2.x开发而成,使用方便.所以研究web安全少不了分析源码,学习代码的同 ...

  9. [ethereum源码分析](3) ethereum初始化指令

    前言 在上一章介绍了关于区块链的一些基础知识,这一章会分析指令 geth --datadir dev/data/02 init private-geth/genesis.json 的源码,若你的eth ...

随机推荐

  1. 使用git上传项目解决码云文件次数上传限制(原文)

    起因:个人免费版的码云上传文件时限制: 1个小时内只能上传20个文件 解决方法:在码云创建空的项目仓库,使用git客户端下载码云的项目,把需要上传的文件复制到该项目中去,用git提交! 1.配置git ...

  2. 密码学笔记——eval(function(p,a,c,k,e,d) 加密破解

    密码学笔记——eval(function(p,a,c,k,e,d) 的加密破解 例题: 小明某天在看js的时候,突然看到了这么一段代码,发现怎么也理不出代码逻辑,你能帮帮他吗? 格式:SimCTF{} ...

  3. bugku 白哥的鸽子

    首先下载之后发现是一个txt 然后更改一下后缀名发现这是一张jpg 图片然后看一下属性然后用hxd分析一下 看看有没有zip 发现没有 然后拖到地下然后发现有一串密码有些问题 然后查一下发现是 栏杆密 ...

  4. 一篇文章了解JsBridge

    链接:https://blog.csdn.net/duwen90/article/details/79389545

  5. 吴裕雄 python 机器学习——数据预处理正则化Normalizer模型

    from sklearn.preprocessing import Normalizer #数据预处理正则化Normalizer模型 def test_Normalizer(): X=[[1,2,3, ...

  6. angular 输入框自动绑定值最长为16位,超过16位则会报错

    最近发现angular在使用input输入框的ng-model绑定scope变量的时候,发现,输入长串的数字将会出错.代码如下: <html> <head> <meta ...

  7. Vue.js 学习入门:介绍及安装

    Vue.js 是什么? Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层 ...

  8. Git - 02. git 版本库简述: 类比平行宇宙

    1. 概述 简单描述 平行宇宙世界观 将 git 与 平行宇宙世界观 做一个类比, 方便理解 熟悉科幻, 或者具体点, 是 漫威宇宙 的朋友, 可以稍微轻松一点 这个是 第一次 重写后的版本. 代码在 ...

  9. python web django 2nd level -- 待更新

    练习代码位置 实例代码位置 --> app: myblog Form 利用Form表单验证,自己写的html 思路: 新建一个类 LoginForm(forms.Form) 新建对象 obj = ...

  10. as中怎么下载更新platforms和build-tools

    链接:https://blog.csdn.net/sunbinkang/article/details/78632652