tp5.1源码分析

下载tp5.1.35

composer create-projecttopthink/think=5.1.35 imooc_tp5 --prefer-dist

执行php think run

php think optimize:autoload 生成classmap.php

自动加载Loader 深度分析

    类的自动加载

注册系统自动加载spl_autoload_register

loader::register

// Composer自动加载支持

autoload_static.php的属性都映射到本类

self::${$attr} = $composerClass::${$attr}

 

// 注册命名空间

addNamespace

会给composer下的autoload_static.php

填充新的内容

$prefixLengthsPsr4

$prefixDirsPsr4

// 注册类库别名Loader::addClassAlias

 

新增自定义类

2、放在thinkphp/library/ali/Send.php


composer下的自动加载

找到composer下的autoload_static.php



解读配置文件

配置文件的种类

1、惯例配置thinkphp/convention.php

2、应用配置config/app.php..

3、模块配置config/index

4、动态配置


php 底层ArrayAccess

提供像访问数组一样访问对象的能力的接口

实现它的四个方法


yaconf扩展

https://github.com/laruence/yaconf下载源码

phpize

./configure --with-php-config=/usr/local/php/bin/php-config

make &&make install

vim php.ini

extension=yaconf.so

yaconf.directory=/usr/local/nginx/html/imooc_tp5/ini


Config底层类分析


Load深度加载

Public/index.php 调用容器的app类,会调用initialize方法,它会调用init方法

其中有一段是调用load方法的


本身$this没有config这个属性,会调用容器种的__get()方法,最后实例化config类,调用load()方法,加载配置文件(多种格式)



Yaml初体验


1、安装pecl install yaml

https://blog.csdn.net/nianyixiaotian/article/details/97017381

2、php -i|grep php.ini


使用方法:

$abc=yaml_parse_file("../config/singwa.yaml");

优化1

框架的bug 需要把环境变量配置的代码提前到$this->configExt



项目中使用

在根目录创建.env   写入CONFIG_EXT=”.yaml”

在控制器层调用



优化2



设计模式

单例模式

注册树模式

依赖注入

1、依赖注入主要用来减少代码间的耦合

2、有效分离对象和它所需的外部资源



PHP的反射机制

Container容器类

编写自己的容器类

包括单例模式、注册树模式、反射机制


实例化



Countable类的使用


Container容器类刨析


获取容器中的对象实例

[if !vml]

[endif]

Make()方法  创建类的实例

[if !vml]

[endif]

[if !vml]

[endif]

[if !vml]

[endif]

在控制器中具体使用容器

[if !vml]

[endif]


门面模式facade

[if !supportLists]1、[endif]门面为容器中的类提供了一个静态调用接口

[if !supportLists]2、[endif]相比于传统的静态方法调用,带来了更好的可测试性和扩展性。


thinkphp\library\think\Facade.php此类是父类

thinkphp\library\think\facade\有很多文件,每个文件只做一件事

继承并返回类的标识。

[if !vml]

[endif]

底层的类不是静态的方法

如thinkphp\library\think\config.php类里不是静态的方法。

上层可以通过静态的方式去用think\xxx.php的方法。


1、dump(\think\facade\Config::get("app."));

2、\think\facade\Config类没有get方法,会调用父类facade类的__callStatic

[if !vml]

[endif]

3、__callStatic的createFacade,创建实例

[if !vml]

[endif]

好处:通过静态的方法调用类的方法。

图示

[if !vml]

[endif]

在控制器中的具体使用

        dump(\Config::get("app."));

       dump(\think\facade\Config::get("app."));

门面模式facade实战

普通的写法

在application\common\Singwa.php

[if !vml]

[endif]

控制器层实例化调用

[if !vml]

[endif]


使用门面模式进行

[if !vml]

[endif]

[if !vml]

[endif]

[if !vml]

[endif]                           

最后在控制器用静态的方式调用

[if !vml]

[endif]

框架执行流程以及路由解读

Container::get('app')找到think\App.php

初始化应用init分析

1、多次初始化

2、检测被多次初始化

$array=debug_backtrace();var_dump($array);

想要知道某方法被在哪调用可以使用它,主要是回溯跟踪。


App.php下的init做的功能

1、加载初始化文件 $path.init.php(本身是没有的,$path是application或具体模块目录)

2、加载行为扩展文件$path.tags.php (application下有此文件)

3、加载公共文件$path.common.php (application下有此文件)

4、加载助手函数helper.php

5、加载中间件 $path.middleware.php(本身是没有的,$path是application或具体模块目录)

6、注册服务的容器对象实例$path.provider.php  然后bindTo($provider)

7、自动读取配置目录文件,并load

8、如果有具体的模块,则对容器中的对象实例进行配置更新


注册服务的容器对象实例

[if !vml]

[endif]

[if !vml]

[endif]

application\common\Sa.php

[if !vml]

[endif]

控制器层

dump(Container::get('sa')->abcd());

路由初始化

initialize方法最后调用

$this->routeInit();

主要工作是扫描根目录的route,引入所有文件。

并导入

[if !vml]

[endif]

Route::get指向的是think\Route.php下的rule方法

[if !vml]

[endif]

http://127.0.0.1:8000/hello/111

Route类种rule方法执行方式脑图

https://naotu.baidu.com/file/bacd378635905a00c7a20bd9ca9d59bf

route.php--->Domain.php--继承-->RuleGroup.php—调用—>addRule方法

路由规则预处理setRule方法

如果是$   则处理成        $this->option['complete_match']= true;

[if !vml]

[endif]

[if !vml]

[endif]

可选的是[:name]=>                                    


[if !vml]

[endif]

$value的结果是

[if !vml]

[endif]

[if !vml]

[endif]

Set的结果是

$this->item[name][]=$value

[if !vml]

[endif]

[if !vml]

[endif]

setRule注册路由规则

$this->rule[$route->getDomain()][$rule][$route->getMethod()]= $route;


$rule路由规则

[if !vml]

[endif]

路由参数

Rule.php 的rule()方法的第四个参数option=[]来表示

Route::get()  //返回的是RuleItem对象

两种方式设置参数

[if !vml]

[endif]

变量规则

Rule.php的rule()方法的第五个参数$pattern

写法

[if !vml]

[endif]

另外一种写法

[if !vml]

[endif]

注册变量规则

[if !vml]

[endif]

资源路由

支持设置restful请求的资源路由,


[if !vml]

[endif]

[if !vml]

[endif]

Route.php定义了rest的几种规则

[if !vml]

[endif]

Resource这个类在library\think\route\Resoure.php

通过资源路由的实例

[if !vml]

[endif]

[if !vml]

[endif]

[if !vml]

[endif]

路由配置--数组方式配置

之前都是调用route类的方法,现在使用返回数组的方式

[if !vml]

[endif]

APP.php的initialize方法,调用了routeInit路由初始化方法

它调用了import方法

import方法做路由规则的导入

[if !vml]

[endif]

Dispatch初始

APP.php的run()方法

[if !vml]

[endif]

打印两个场景

[if !supportLists]1、[endif]通过路由配置

[if !supportLists]2、[endif]普通的,没有经过配置的

无论是什么模式,最后$dispatch的结果都是

[if !vml]

[endif]

上上图中的routeCheck()方法种有url路由检测

[if !vml]

[endif]

最后return $dispatch

而check()方法

[if !vml]

[endif]

[if !vml]

[endif]

request类如何找到

上上图中的$this->request,是Route.php的属性,

[if !vml]

[endif]

[if !vml]

[endif]

没有容器则创建容器

[if !vml]

[endif]

调用container.php的make方法,会找到Request.php



DOmain.php->check()------RuleGroup.php->check()

检测url变量和规则路由是否匹配

Route.php -->check()检测url路由

Domain.php->check()检测域名路由parent::check($request, $url, $completeMatch)

RuleGroup.php->check()检测分组路由

RuleGroup.php->checkMergeRuleRegex()检测分组路由

[if !vml]

[endif]

RuleItem.php-> checkRule()检测路由


其中会调用match()方法主要是检测url变量和规则路由是否匹配

dump($match)时变量数组

控制器解读

课前复习

匿名函数

在php5.3及以上版本

匿名函数,也叫闭包函数,允许临时创建一个没有指定名称的函数。

[if !vml]

[endif]

Eg2:匿名函数作为函数的参数访问

Demo(function(){return“####”})

闭包

连接闭包和外界变量的关键字:USE

闭包可以保存所在代码块上下文的一些变量和值。

PHP在默认情况下,匿名函数不能调用所在代码块的上下文变量,而需要通过使用use关键字

[if !vml]

[endif]

匿名函数作为返回值返回

[if !vml]

[endif]

通俗的说:子函数可以使用父函数中的局部变量,这种行为就叫做闭包!

闭包函数返回时,该函数内部变量处于激活状态,函数所在栈区依然保留


实例化控制器

App.php run()方法

[if !vml]

[endif]

[if !vml]

[endif]

调用该类的run()

[if !vml]

[endif]

在本类是抽象方法,在Module.php中实现

[if !vml]

[endif]

[if !vml]

[endif]

实例化控制器

[if !vml]

[endif]

执行控制器中的方法

Module.php 中的exec()方法

[if !vml]

[endif]

[if !vml]

[endif]

[if !vml]

[endif]

[if !vml]

[endif]

$data时方法最后的return “hello world”

闭包返回的数据,最后注册到中间件中

执行autoResponse调度

[if !vml]

[endif]

[if !vml]

[endif]

第一次走的是elseif  执行Response::create()方法

[if !vml]

[endif]

实例化的时候会调用构造方法,

[if !vml]

[endif]


最后autoResponse返回的的结果是

以及

[if !vml]

[endif]

返回的结果是一样的

[if !vml]

[endif]

[if !vml]

[endif]

[if !vml]

[endif]

执行中间件的调度


输出数据到终端

[if !vml]

[endif]

fastcgi_finish_request()

客户端响应到此结束,服务端代码还是会去执行

控制器的初始化

[if !vml]

[endif]



trait特性讲解

php以前是单继承的,无法同时继承多个类

trait jump类

[if !vml]

[endif]

[if !vml]

[endif]

DB和模型

DB操作

Db::query($sql)

Db需要use \think\Db

query这个静态方法是没有的

 \think\Db.php类文件没有query方法,会调用__callStatic()方法

会调用本类的static::connect()方法,主要是用来切换数据库连接

[if !vml]

[endif]

[if !vml]

[endif]

[if !vml]

[endif]

$this->connection 是Connection.php 下的Mysql的实例,它在connector下,Mysql.php没有query方法,去父类找query()


Db类库结合连接器、查询器、生成器

$res=DB::table('imooc_user')->where(['id'=>1])->find();

没有tabe方法,会调用__callStatic()方法

call_user_func_array([static::connect(),$method], $args);

这里是 static::connect是结果new Query

table 在此类中,where也一样,find 方法会

$result = $this->connection->find($this);

而connection是依赖注入的方式find(Query $query)

此方法中有生成器

// 生成查询SQL

$sql = $this->builder->select($query);

builder中的select方法主要是使用str_replace替换下列字符串中的字符


SELECT%DISTINCT% %FIELD% FROM %TABLE%%FORCE%%JOIN%%WHERE%%GROUP%%HAVING%%UNION%%ORDER%%LIMIT%

%LOCK%%COMMENT%

model场景

[if !vml]

[endif]


model场景分析--新增逻辑

print_r(model('user'));


app\index\model\User Object ( [data] => Array ( ) [relation]

=> Array ( ) )


save()方法在model.php

在此方法中调用本类的checkBeforeSave()方法,主要功能是写入之前检查数据

checkBeforeSave调用setAttr

[if !vml]

[endif]

setAttr方法


// 检测修改器$method = 'set' . Loader::parseName($name, 1) . 'Attr';

最后形成

// 设置数据对象属性

return$this->data[$name] = $value;

深度分析

设置完属性对象,逻辑还是回到save()方法中,接着进行insertData方法

[if !vml]

[endif]

[if !vml]

[endif]

其中上上图的insert方法

[if !vml]

[endif]

[if !vml]

[endif]

最后在此方法中执行execute()




异常处理、缓存

Base.php有类的关系映射,通过\Cache找到对应的门面模式

通过配置文件设置需要type是文件,redis,memcache,

通过工厂模式进行调用

面试技巧

MySQL基本使用、优化(加索引、主从分离,读写分离),查询elecsearch

redis场景投票、抢票、排序

Nginx 基本配置限流,负载均衡

框架:深入理解框架就够了

简历体现技术难点

内推:算法,数据结构


框架层:设计模式、门脸模式、迭代器、反射、类自动加载、路由


对框架的理解

[if !supportLists]1、[endif]组织好目录结构,如应用目录,配置目录,

[if !supportLists]2、[endif]入口文件处理自动加载(框架层的自动加载,composer的自动加载)

[if !supportLists]3、[endif]容器(单例模式)

[if !supportLists]4、[endif]配置文件的加载(tp配置文件写在文件里,对性能有损耗,yaconf)

[if !supportLists]5、[endif]路由(中大型公司用不到,在nginx做配置就可以)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 对于java中的思考的方向,1必须要看前端的页面,对于前端的页面基本的逻辑,如果能理解最好,不理解也要知道几点。 ...
    神尤鲁道夫阅读 4,262评论 0 0
  • tp5.1运行环境要求PHP5.6+ 对比5.0 1、采用容器统一管理对象2、facade支持3、对象化路由4、取...
    余头阅读 4,671评论 0 0
  • Sonar翻译 Sonar翻译... 1 User Guide(用户指南)... 2 第一章Fixing the ...
    pig_zzZ阅读 8,057评论 0 1
  • CHAPTER 1: INTRODUCTION 第一章:简介 In this chapter, we discus...
    哈小奇阅读 4,642评论 2 1
  • 当天我就把想法落实到行动上,我名下唯一的财产就是这辆车,我把车过户到朋友的名下,对方要是问起就说是买的,另...
    汇誉通阅读 1,783评论 0 0

友情链接更多精彩内容