服务容器

介绍

Lumen 服务容器是管理类依赖的强力工具。依赖注入是比较专业的说法,真正意思是将类依赖通过构造器或 「setter」 方法注入。

基本用法

Note: 为了保证程序的整洁, 建议放置于 服务提供者 里面.

注册基本解析器

服务容器注册依赖有几种方式,包括闭包回调和绑定实例的接口。首先,我们来探讨闭包回调的方式。被注册至容器的闭包解析器包含一个 key (通常用类名称) 和一个有返回值的闭包:

  1. $app->bind('FooBar', function($app) {
  2. return new FooBar($app['SomethingElse']);
  3. });

注册一个单例

有时候,你可能希望绑定到容器的对象只会被解析一次,之后的调用都返回相同的实例:

  1. $app->singleton('FooBar', function($app) {
  2. return new FooBar($app['SomethingElse']);
  3. });

绑定一个已经存在的实例

你也可以使用 instance 方法,绑定一个已经存在的实例到容器,接下来将总是返回该实例:

  1. $fooBar = new FooBar(new SomethingElse);
  2. $app->instance('FooBar', $fooBar);

解析

从容器解析出实例有几种方式。
一、可以使用 make 方法:

  1. $fooBar = $app->make('FooBar');

自动解析

二、你可以在构造函数中简单地「类型指定(type-hint)」你所需要的依赖,包括在控制器、事件监听器、队列任务,过滤器等等之中。容器将自动注入你所需的所有依赖:

  1. <?php namespace App\Http\Controllers;
  2. use App\Http\Controllers\Controller;
  3. use App\Users\Repository as UserRepository;
  4. class UserController extends Controller {
  5. /**
  6. * The user repository instance.
  7. */
  8. protected $users;
  9. /**
  10. * Create a new controller instance.
  11. *
  12. * @param UserRepository $users
  13. * @return void
  14. */
  15. public function __construct(UserRepository $users)
  16. {
  17. $this->users = $users;
  18. }
  19. /**
  20. * Show the user with the given ID.
  21. *
  22. * @param int $id
  23. * @return Response
  24. */
  25. public function show($id)
  26. {
  27. //
  28. }
  29. }

将接口绑定到实现

服务容器有个非常强大特色,能够绑定特定实例的接口。举例,假设我们应用程序要集成 Pusher 服务去收发即时事件,如果使用 Pusher 的 PHP SDK,可以在类注入一个 Pusher 客户端实例.

可以在服务容器像这样注册它:

  1. $app->bind('App\Contracts\EventPusher', 'App\Services\PusherEventPusher');

当有类需要 EventPusher 接口时,会告诉容器应该注入 PusherEventPusher,现在就可以在构造器中「类型指定」一个 EventPusher 接口:

  1. /**
  2. * Create a new order handler instance.
  3. *
  4. * @param EventPusher $pusher
  5. * @return void
  6. */
  7. public function __construct(EventPusher $pusher)
  8. {
  9. $this->pusher = $pusher;
  10. }

上下文绑定

有时候,你可能会有两个类需要用到同一个接口,但是你希望为每个类注入不同的接口实现。例如当我们的系统收到一个新的订单时,我们需要使用 PubNub 来代替 Pusher 发送消息。Lumen 提供了一个简单便利的接口来定义以上的行为:

  1. $app->when('App\Service\CreateOrder')
  2. ->needs('App\Contracts\EventPusher')
  3. ->give('App\Services\PubNubEventPusher');

标签

偶尔你可能需要解析绑定中的某个「类」。例如你正在建设一个汇总报表,它需要接收实现了 Report 接口的不同实现的数组。在注册了 Report 的这些实现之后,你可以用 tag 方法来给他们赋予一个标签:

  1. $app->bind('SpeedReport', function() {
  2. //
  3. });
  4. $app->bind('MemoryReport', function() {
  5. //
  6. });
  7. $app->tag(['SpeedReport', 'MemoryReport'], 'reports');

一旦服务打上标签,可以通过 tagged 方法轻易地解析它们:

  1. $app->bind('ReportAggregator', function($app) {
  2. return new ReportAggregator($app->tagged('reports'));
  3. });

容器事件

注册一个解析事件监听器

容器在解析每一个对象时就会触发一个事件。你可以用 resolving 方法来监听此事件:

  1. $app->resolving(function($object, $app) {
  2. // Called when container resolves object of any type...
  3. });
  4. $app->resolving(function(FooBar $fooBar, $app) {
  5. // Called when container resolves objects of type "FooBar"...
  6. });

被解析的对象将被传入到闭包方法中。