当前位置: 首页 > 文档资料 > Lumen 中文文档 >

1.5.2 服务容器

优质
小牛编辑
127浏览
2023-12-01

介绍

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

基本用法

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

注册基本解析器

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

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

注册一个单例

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

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

绑定一个已经存在的实例

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

$fooBar = new FooBar(new SomethingElse);

$app->instance('FooBar', $fooBar);

解析

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

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

自动解析

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

<?php namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Users\Repository as UserRepository;

class UserController extends Controller {

    /**
     * The user repository instance.
     */
    protected $users;

    /**
     * Create a new controller instance.
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }

    /**
     * Show the user with the given ID.
     *
     * @param  int  $id
     * @return Response
     */
    public function show($id)
    {
        //
    }

}

将接口绑定到实现

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

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

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

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

    /**
     * Create a new order handler instance.
     *
     * @param  EventPusher  $pusher
     * @return void
     */
    public function __construct(EventPusher $pusher)
    {
        $this->pusher = $pusher;
    }

上下文绑定

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

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

标签

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

$app->bind('SpeedReport', function() {
    //
});

$app->bind('MemoryReport', function() {
    //
});

$app->tag(['SpeedReport', 'MemoryReport'], 'reports');

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

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

容器事件

注册一个解析事件监听器

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

$app->resolving(function($object, $app) {
    // Called when container resolves object of any type...
});

$app->resolving(function(FooBar $fooBar, $app) {
    // Called when container resolves objects of type "FooBar"...
});

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