首先抛出我的疑问:

  1. laravel的底层是如何处理HTTP请求的?
  2. laravel的Request是如何实现的?
  3. 为什么不需要配置Nginx的url解析,也不需要在laravel的router中配置参数名称,却可以通过Request接收到参数呢?实现原理是什么?

下面开始进入查源码之旅:

  1. 首先调研了一下laravel的request是基于什么实现的?
  2. 知识点如下:laravel的很多底层组件是基于Symfony实现的,比如:请求、响应、cookie、命令行,文件等。其中HttpFoundation组件是http请求中比较重要的基础组件,它可以独立于Symfony使用的,laravel基于此做了进一步的封装,使用示例如下
$request->input('param');
$request->cookie('cookie');
$request->file('file');
  1. 考虑到laravel项目所有的HTTP请求都会转发到laravel的入口文件(public/index.php),所以我们查看这个文件一探究竟:
//创建Application实例,作为服务容器
$app = new Illuminate\Foundation\Application(realpath(__DIR__.'/../')
);//以单例方式在服务容器中将 App\Http\Kernel 实例绑定到 Illuminate\Contracts\Http\Kernel 接口
$app->singleton(Illuminate\Contracts\Http\Kernel::class,App\Http\Kernel::class
);//服务容器创建处理 HTTP 请求的内核实例(Kernel)
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);//核心方法:处理 HTTP 请求的核心代码(核心代码会在下一部分展开来讲,先从上而下理清流程)
$response = $kernel->handle($request = Illuminate\Http\Request::capture()
);//发送响应给发送请求的客户端
$response->send();//内核实例终止程序,基于传入的request和response做一些收尾工作
$kernel->terminate($request, $response);
  1. 上面的注释已经比较清楚的解释了laravel处理HTTP请求的内部实现流程。
  2. 我们再继续深入核心代码,研究一下“laravel为什么在路由中无需指定参数是什么,在控制器方法中传入Request就可以获得参数了呢?”

比如:

//路由
Route::resource('/index', 'IndexController');//controller中的方法
function index(Request $request)
{switch ($request->type) {...}
}
  1. 下面的非核心代码用竖着的3个.省略,避免误导
//laravel项目的入口文件 index.php...//重点1:handle()方法
$response = $kernel->handle($request = Illuminate\Http\Request::capture()
);...//深入源码1 capture()
public static function capture()
{static::enableHttpMethodParameterOverride();//重点2:createFromBase() 方法return static::createFromBase(SymfonyRequest::createFromGlobals());
}//我们再深入源码2 createFromBase()
public static function createFromBase(SymfonyRequest $request)
{if ($request instanceof static) {return $request;}$content = $request->content;//这是解决疑问的关键代码 duplicate 意为复制一份$request = (new static)->duplicate($request->query->all(), $request->request->all(), $request->attributes->all(),$request->cookies->all(), $request->files->all(), $request->server->all());$request->content = $content;$request->request = $request->getInputSource();return $request;
}
  1. 发现了一个神奇的方法:duplicate(),意为复制一份。
  2. duplicate()方法的参数,包括$request->query->all(), $request->request->all()…等,即底层已经实现了所有query和request的接收,我们不需要单独声明也是可以接收到所有请求参数的。
$request = (new static)->duplicate($request->query->all(), $request->request->all(), $request->attributes->all(),$request->cookies->all(), $request->files->all(), $request->server->all()
);
  1. 上面就是我查询源码的流程:

    1. 明确自己的问题(Request的底层实现)
    2. 明确自己排查问题的边界(从入口文件入手)
    3. 一层一层的深入查询源码(源码1->源码2–>源码3)
    4. 排除非核心代码,找到最核心代码(duplicate()方法)
  2. 下面是另外一位博主的思考总结,个人觉得总结的更系统和专业,laravel底层如何处理HTTP请求,而我的总结更体现出我带着问题查看源码的思路、流程、反思、总结。

  3. 还有一个小插曲:
    源码这么写的原因是什么?不是重复操作吗?

  4. 不认真呀,仔细看一下,2中的request是通过 (new static)->duplicate()克隆的新对象,和1中的request并不是相同的实例。

文章结尾,放两个小题供大家消遣一下。

  1. 请设计一个函数,实现以下功能:将字符串"wang_zhong_yang"转换成"WangZhongYang";

1.1 我的解题思路:

   public function actionCreate(){$str1 = "wang_zhong_yang";$arr1 = explode("_",$str1);foreach ($arr1 as $value){$str2 .=ucfirst($value);}var_dump($str2);}
  1. 请再设计一个函数,将字符串"wang_zhong_yang"转换成"wAngzHongyAng";

2.2 我的解题思路:

    public function actionCreate(){$str1 = "wang_zhong_yang";$arr1 = explode("_",$str1);foreach ($arr1 as $value){//拆分$first = substr($value,0,1);$sec = substr($value,1,1);$sec = strtoupper($sec);$third = substr($value,2,strlen($value));$final = $first . $sec.$third;$str2 .= $final;}var_dump($str2);}

我上面2道题的解法思路肯定不是最优解,欢迎大家不吝赐教。

总结和思考:

我们每次遇到不懂的知识点,是选择“马马虎虎会用就行”,还是选择“知其然,还知其所以然”,这2种选择在N年后给我们带来的结果是完全不同的。

反思自己之前做项目一把solo代码,搬砖赶进度,不求甚解有些汗颜。

在deadline之前,把需求搞定的同时,还是要尽可能多的搞清楚底层实现原理是什么。

最后,送给大家:

每日精进,如春起之苗,不见其长,日有所长。

如何通过查源码的方式解决编程中遇到的问题?查源码定位问题的思路是什么?相关推荐

  1. 如何解决编程中Excel不能读取的问题

    如何解决编程中Excel不能读取的问题 首先,这里提供的解决办法仅适用于出现如下异常的情况: 无法将类型为"Microsoft.Office.Interop.Excel.Applicatio ...

  2. 用类比方式学习编程中函数递归(个人理解仅供参考)(内含汉诺塔问题的求解)

    目录 1.前言 2.递归的数学模型 3.相关的c语法 4.将递归的数学模型写成编程语言 5.利用类比方法将实际问题的代码写成函数递归的形式 例1: 例2: 6.汉诺塔问题的求解 1.前言 本人在学习函 ...

  3. url 参数传递的两种方式_VB编程中的传值与传址两种参数传递方式,你清楚吗?...

    Tips:欢迎公众号设置为星标,VB技术干货文章可以第一时间看到.如您在学习VB过程中有独特的见解或者想法,欢迎投稿,可在公众号文章下直接留言. 推荐阅读 1. VB编程语言基础知识点总结 2. VB ...

  4. JUC并发编程中的集合不安全问题源码解析

    JUC并发编程四:集合不安全(Java) 1.List不安全! 代码示例: package unsafe;import java.util.*; import java.util.concurrent ...

  5. v html如何添加样式,详解三种方式解决vue中v-html元素中标签样式

    Vue为v-html中标签添加CSS样式 {{news.title}} {{news.datetime}} 返回列表 当我们使用v-html渲染页面,使用下面这种方式去修改样式并没有效果, .con{ ...

  6. vue v-html字体大小修改,详解三种方式解决vue中v-html元素中标签样式

    Vue为v-html中标签添加CSS样式 {{news.title}} {{news.datetime}} 返回列表 当我们使用v-html渲染页面,使用下面这种方式去修改样式并没有效果, .con{ ...

  7. ov7670 linux源码,STM32 迷你照相机 OV7670 摄像头 - 源码下载|嵌入式/单片机编程|微处理器(ARM/PowerPC等)|源代码 - 源码中国...

    压缩包 : STM32F_OV7670.rar 列表 uVision3/FLASH.ini uVision3/Simple Wave Player.opt.bak uVision3/Simple Wa ...

  8. jsr 正则验证_使用 Bean Validation 解决业务中参数校验

    痛点及现状 代码中常常见到如下代码: if (Objects.equal(0L ,repertory)){ return ApiResultMap.errorResult(-1 ,"操作数量 ...

  9. 数据转换成二维码并导出进Excel中和导入时解码二维码反转成数据

    数据转换成二维码并导出进Excel中和导入时解码二维码反转成数据 第一步在maven中配置需要的二维码jar包 1.1 谷歌提供的帮助类 1.2 关于二维码的工具类 1.3 测试类 第二步 在Exce ...

最新文章

  1. 【转】Java finally语句到底是在return之前还是之后执行?
  2. 函数默认形参与占位参数
  3. LeetCode 1522. Diameter of N-Ary Tree(递归)
  4. springMVC导入excel案例poi
  5. javascript框架比较(二)
  6. 双十一清醒指南,送3本Python书
  7. 程序员思维看爱情是什么?
  8. java中mydoc_实验二/MyDoc.java · 20175326李一潇/20175326java - Gitee.com
  9. usermod 添加用户多个附属组
  10. 人工智能代码自动生成技术的一点思考
  11. 基于Matlab/GUI界面设计的参数在线整定与优化(一)
  12. List转Map的几种方式
  13. Python函数学习心得
  14. 电脑不允许被PING的解决办法
  15. 测试象棋水平用哪个软件好,最新象棋软件作弊名单公布,软件测试员都被封,哪些网络象棋主播...
  16. 【土旦】在vue filters中 优雅的使用对象的key、value来替换 if switch多重判断简化流程...
  17. MySQL性能优化的最佳20+条经验
  18. 二维码制作软件那个好用?
  19. Crosslink-NX器件应用案例(2): MIPI的多源合成(MUX)与分发(DeMUX)
  20. linux之打包压缩(tar,gz,bz2,xz,zip)

热门文章

  1. 泛微数字化项目风险管理平台:预警、评估、上报一体化
  2. wordpress表单数据验证_手拉手搭建 lnmp 环境及安装 wordpress
  3. Web应用技术(第十周和第十一周/3h)
  4. Python 学习 --->Anaconda、pyenv、virtualenv、venv
  5. HTML+CSS+JS练手小玩意
  6. 关于Linux进程介绍
  7. 自动文摘系统实现总结
  8. simulink simscape模型报错解决:Cannot reload workspace from non-existing data source file
  9. 申宝在线炒股沪指下探回升
  10. 使用LogParser和WCAT进行iis压力测试