Laravel 依赖注入源码解析

栏目: PHP · 发布时间: 8年前

内容简介:Laravel 依赖注入源码解析

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

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 方法,“顾名思义”这个方法的作用是从类的方法中获取依赖对象:

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.

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


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

中国机器人

中国机器人

[中]王鸿鹏、[中]马娜 / 辽宁人民出版社 / 2017-1-1 / 48.00元

本书对中国机器人领域的发展历史做了引人入胜的介绍,中国机器人成长的过程也是中国经济由弱到强的历程。本书实际是选择了一个独特的视角来解读中国数十年的政治、经济、国家战略问题。中国的未来充满了多重可能性,本书对想了解中国当代与未来发展战略的读者是难得的读本,对智能制造这一当今世界*受关注的高科技领域在战略层面和科技伦理层面进行了深入地剖析和思考,其中提出的诸多前沿性观点是全球都将面对的问题,对中国科学......一起来看看 《中国机器人》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换