通过源码解析Laravel的依赖注入


Posted in PHP onJanuary 22, 2018

前言

众所周知,php的框架数不胜数,近几年,一个以优雅著称的框架,渐渐被国内phper所知道,并且开始使用,但是larave有一个很明显的缺点就是,他的文档内容少的可怜。

本文将给大家详细介绍关于Laravel依赖注入的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

在 Laravel 的控制器的构造方法或者成员方法,都可以通过类型约束的方式使用依赖注入,如:

public function store(Request $request)
{
 //TODO
}

这里 $request 参数就使用了类型约束,Request 是一个类:\Illuminate\Http\Request,表示参数必须是这个类或子类。

本文通过分析 Laravel 的源码,看为什么方法中不需要传入实例就可以直接使用 Request 呢?只是框架自动帮我们实例化并传参了。

1.路由定义

从源头开始看起,在路由定义文件中定义了这么一个路由:

Route::resource('/role', 'Admin\RoleController');

这是一个资源型的路由,Laravel 会自动生成增删改查的路由入口。

通过源码解析Laravel的依赖注入

本文开头的 store 方法就是一个控制器的方法,图中可见路由定义的 Action 也是:App\Http\Controllers\Admin\RoleController@store

路由方法解析

根据路由定义找到控制器和方法,执行具体的方法在 dispatch 方法中实现。

(文件:vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php)

public function dispatch(Route $route, $controller, $method)
{
 $parameters = $this->resolveClassMethodDependencies(
  $route->parametersWithoutNulls(), $controller, $method
 );
 
 if (method_exists($controller, 'callAction')) {
  return $controller->callAction($method, $parameters);
 }
 
 return $controller->{$method}(...array_values($parameters));
}

首先 resolveClassMethodDependencies 方法,“顾名思义”是根据类的方法参数获取依赖对象,然后再调用类的方法并把对象参数注入。

如果有多个依赖对象,也会 foreach 依次解析出来作为参数注入。

获取依赖对象示例的代码:

protected function resolveClassMethodDependencies(array $parameters, $instance, $method)
{
 if (! method_exists($instance, $method)) {
  return $parameters;
 }
 
 return $this->resolveMethodDependencies(
  $parameters, new ReflectionMethod($instance, $method)
 );
}

这里重点就是用到了 PHP 的反射,注意 RelectionMethod 方法,它获取到类的方法参数列表,可以知道参数的类型约束,参数名称等等。

这里的 $instance 参数就是 RoleController 控制器类,$method 参数就是方法名称 strore.

2.获取依赖对象的示例

从方法的参数中获取了依赖对象的约束类型,就可以实例化这个依赖的对象。

protected function transformDependency(ReflectionParameter $parameter, $parameters)
{
 $class = $parameter->getClass(); 
 // If the parameter has a type-hinted class, we will check to see if it is already in
 // the list of parameters. If it is we will just skip it as it is probably a model
 // binding and we do not want to mess with those; otherwise, we resolve it here.
 if ($class && ! $this->alreadyInParameters($class->name, $parameters)) {
  return $parameter->isDefaultValueAvailable()
   ? $parameter->getDefaultValue()
   : $this->container->make($class->name);
 }
}

根据类名从容器中获取对象,这个绑定对象实例的过程在服务提供者中先定义和了。

然后把实例化的对象传入到 store 方法中,就可以使用依赖的对象了。

3.关于 PHP 反射

举个使用 ReflectionMethod 的例子。

class Demo
{
 private $request;
 public function store(Request $request)
 {
 }
}

打印出 new ReflectionMethod(Demo::class, ‘store') 的内容如图:

通过源码解析Laravel的依赖注入

可以得出这个方法的参数列表,参数的约束类型,如 typeHint,Illuminate\Http\Request.

根据类名可以从容器中获取一开始通过服务提供者绑定的实例。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
PHP源码之explode使用说明
Aug 05 PHP
php数组合并array_merge()函数使用注意事项
Jun 19 PHP
怎样搭建PHP开发环境
Jul 28 PHP
Symfony2使用第三方库Upload制作图片上传实例详解
Feb 04 PHP
PHP设计模式之迭代器模式
Jun 17 PHP
thinkphp 手机号和用户名同时登录
Jan 20 PHP
PHPCrawl爬虫库实现抓取酷狗歌单的方法示例
Dec 21 PHP
Yii2 中实现单点登录的方法
Mar 09 PHP
php高清晰度无损图片压缩功能的实现代码
Dec 09 PHP
laravel利用中间件做防非法登录和权限控制示例
Oct 21 PHP
PhpSpreadsheet设置单元格常用操作汇总
Nov 13 PHP
解决thinkphp6(tp6)在状态码500下不报错,或者显示错误“Malformed UTF-8 characters”的问题
Apr 01 PHP
phpstorm 正则匹配删除空行、注释行(替换注释行为空行)
Jan 21 #PHP
php语言注释,单行注释和多行注释
Jan 21 #PHP
PHP注释语法规范与命名规范详解篇
Jan 21 #PHP
php nginx 实时输出的简单实现方法
Jan 21 #PHP
Lumen timezone 时区设置方法(慢了8个小时)
Jan 20 #PHP
PHP Class SoapClient not found解决方法
Jan 20 #PHP
tp5(thinkPHP5)操作mongoDB数据库的方法
Jan 20 #PHP
You might like
苏联队长,苏联超人蝙蝠侠,这些登场的“山寨”英雄真的很严肃
2020/04/09 欧美动漫
支持数组的ADDSLASHES的php函数
2010/02/16 PHP
PHP操作文件类的函数代码(文件和文件夹创建,复制,移动和删除)
2011/11/10 PHP
php函数array_merge用法一例(合并同类数组)
2013/02/03 PHP
php实现简单洗牌算法
2013/06/18 PHP
解析crontab php自动运行的方法
2013/06/24 PHP
迅速确定php多维数组的深度的方法
2014/01/07 PHP
php在数据库抽象层简单使用PDO的方法
2015/11/03 PHP
JQuery困惑—包装集 DOM节点
2009/10/16 Javascript
JS Pro-深入面向对象的程序设计之继承的详解
2013/05/07 Javascript
探讨JavaScript中声明全局变量三种方式的异同
2013/12/03 Javascript
javascript实现类似于新浪微博搜索框弹出效果的方法
2015/07/27 Javascript
js实现简单的手风琴效果
2017/02/27 Javascript
ng2学习笔记之bootstrap中的component使用教程
2017/03/09 Javascript
JS获取字符对应的ASCII码实例
2017/09/10 Javascript
vue滚动轴插件better-scroll使用详解
2017/10/17 Javascript
AngularJS 控制器 controller的详解
2017/10/17 Javascript
vue环境搭建简单教程
2017/11/07 Javascript
JS实现统计字符串中字符出现个数及最大个数功能示例
2018/06/04 Javascript
vue生命周期的探索
2019/04/03 Javascript
Vue实现购物车详情页面的方法
2019/08/20 Javascript
Layui Form 自定义验证的实例代码
2019/09/14 Javascript
vue实现导航菜单和编辑文本的示例代码
2020/07/04 Javascript
vue3.0 自适应不同分辨率电脑的操作
2021/02/06 Vue.js
详细介绍pandas的DataFrame的append方法使用
2019/07/31 Python
Python实现串口通信(pyserial)过程解析
2019/09/25 Python
python实现按键精灵找色点击功能教程,使用pywin32和Pillow库
2020/06/04 Python
HTML5 Canvas实现图片缩放、翻转、颜色渐变的代码示例
2016/02/28 HTML / CSS
管理专员自荐信
2014/01/26 职场文书
医学生自我鉴定范文
2014/03/26 职场文书
《风娃娃》教学反思
2014/04/19 职场文书
学校教师安全责任书
2014/07/23 职场文书
党纪处分决定书
2015/06/24 职场文书
微信早安问候语
2015/11/10 职场文书
Win11使用CAD卡顿或者致命错误怎么办?Win11无法正常使用CAD的解决方法
2022/07/23 数码科技
Sentry的安装、配置、使用教程(Sentry日志手机系统)
2022/07/23 Python