PHP 从另外一个角度来分析 Laravel 框架的依赖注入功能

从根本上说,依赖注入不是让对象建立一个依赖关系,也不是让工厂对象去建立对象,而是将所需的依赖变成一个外部对象,使之成为一个"某些人的问题”

你为"某些人的问题”注入了类的依赖关系。在Laravel中,这个"某人”是 服务容器 。在Laravel中,服务容器负责经过构造函数注入类的依赖关系。php

任什么时候候,你在一个控制器类中请求一个依赖,这个服务容器负责:laravel

  1. 自动地在构造函数中检测依赖关系
  2. 若是须要构建这个依赖关系
  3. 经过构造函数建立对象造成依赖关系

来看一个很是简单的例子。sql

 1 <?php
 2 namespace App\Http\Controllers;
 3 use App\User;
 4 use App\Repositories\UserRepository;
 5 use App\Http\Controllers\Controller;
 6 class UserController extends Controller
 7 {
 8     protected $userRepository;
 9     public function __construct(UserRepository $userRepository)
10     {
11         $this->userRepository = $userRepository;
12     }
13     public function show($id)
14     {
15         $user = $this->userRepository->find($id);
16         return view('user.profile', ['user' => $user]);
17     }
18 }

 

假如,你有一个 UserController 类须要 UserRepository 做为一个构造函数依赖。shell

  1. 服务容器使用 PHP 的 反射类 来检测,事实 UserRepository 须要被优先解析。
  2. 而后,它构造 UserRepository 实例。
  3. 而后,它构造 UserController 类实例。

依赖关系是如何被解析和注入的,我被不少 Laravel 开发人员不知道这个简单而强大的技术感到迷惑。 这是一个很是强大的技术,它能够被用来解决复杂对象的依赖关系。缓存

若是因为某种缘由,您不但愿Laravel自动构建一个对象,您还能够经过传递一个可用于建立依赖关系的回调来告诉Laravel Service Container如何构造该对象。服务器

1 <?php
2 $container->bind('My\Service', function($container) {
3   return new My\Service($container->make('My\AnotherService'));
4 });

 

您须要建立一个服务提供商来注册上述服务。架构

 1 <?php
 2 namespace App\Providers;
 3 use Illuminate\Support\ServiceProvider;
 4 class MyServiceProvider extends ServiceProvider
 5 {
 6     public function register()
 7     {
 8         $this->app->singleton(\My\Service::class, function ($app) {
 9             return new \My\Service($app->make('My\AnotherService'));
10         });
11     }
12 }

 

当 My\Service 须要被解析的时候,负责返回一个对象的回调函数就会被调用。并发

 1 <?php
 2 namespace App\Http\Controllers;
 3 use App\User;
 4 use App\Http\Controllers\Controller;
 5 class MyController extends Controller
 6 {
 7     protected $myService;
 8     public function __construct(\My\Service $myService)
 9     {
10         $this->myService = $myService;
11     }
12     // .. 方法
13 }

 

真实的例子

假设你的应用须要Facebook的PHP SDK来访问Facebook的API,你的控制器就是这样的:app

 1 <?php
 2 namespace App\Http\Controllers;
 3 use App\User;
 4 use App\Http\Controllers\Controller;
 5 use Facebook\Facebook;
 6 class FacebookApiAccessController extends Controller
 7 {
 8     protected $facebook;
 9     public function __construct(Facebook\Facebook $facebook)
10     {
11         $this->facebook = $facebook;
12     }
13     //.. action methods here
14 }

 

如今,您须要告诉Service Container如何构建 Facebook\Facebook的实例.分布式

1 <?php
2 $container->singleton('Facebook\Facebook', function() {
3   return new \Facebook\Facebook([
4     'app_id' => config('services.facebook.app_id'),
5     'app_secret' => config('services.facebook.app_secret'),
6     'default_graph_version' => 'v2.10',
7   ]);
8 });

 

注意,我已经调用了方法singleton而不是bind。 惟一的区别是用singleton注册的服务被缓存,随后的解析服务调用返回缓存的服务。

结论

依赖注入是一种强大的技术,你能够在 Laravel 中用来简化对象的建立. 默认状况下, Laravel 的服务容器会自动的用反射去检测和解决依赖关系. 可是, 你能够指定回调来解析服务.

phper在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提高,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货须要的能够免费分享给你们,须要的(点击→)个人官方群677079770

相关文章
相关标签/搜索