Laravel服务提供商解释

时间:2016-08-17 14:32:43

标签: php laravel symfony

我对Laravel服务提供商并不熟悉,我对此有疑问。

示例:我有三个类SystemProfiler,SurveyProfiler和OfferProfiler,它们实现了ProfilerInterface。我还有ProfilerService类,它在构造函数中注入了ProfilerInterface。我需要创建不同的ProfilerService服务,并注入每个分析器。

ProfilerService:

system_profiler:
    class: App\MyBundle\Profiles\SystemProfiler

survey_profiler:
    class: App\MyBundle\Profiles\SurveyProfiler

offer_profiler:
    class: App\MyBundle\Profiles\OfferProfiler

system_profile_service:
    class: App\MyBundle\Services\ProfilerService
    arguments:
        - system_profiler

survey_profile_service:
    class: App\MyBundle\Services\ProfilerService
    arguments:
        - survey_profiler

offer_profile_service:
    class: App\MyBundle\Services\ProfilerService
    arguments:
        - offer_profiler

我知道如何在symfony2框架中执行此操作:

$this->container->get()

然后只需使用ProfilerService实现的别名调用 $this->app->bind('App\MyBundle\Contracts\ProfilerInterface','App\MyBundle\Profiles\SystemProfiler');

但是Laravel文档说“如果它们不依赖于任何接口,则不需要将类绑定到容器中。”。而ProfilerService不依赖于接口。所以我可以将每个探查器绑定到接口,如下所示:

$this->app->bind('App\MyBundle\Contracts\ProfilerInterface','App\MyBundle\Profiles\SurveyProfiler');

$this->app->bind('App\MyBundle\Contracts\ProfilerInterface','App\MyBundle\Profiles\OfferProfiler');

{{1}}

但我应该如何绑定哪些Profilers应该注入ProfilerService以及何时???

我将不胜感激任何帮助和解释

2 个答案:

答案 0 :(得分:2)

ProfilerService的构造函数键入一个接口,这意味着您的ProfilerService确实依赖于接口。

如果您没有进行任何其他设置,如果您尝试App::make('App\MyBundle\Services\ProfilerService');,则会出现错误,因为Laravel不知道如何解决接口依赖关系。

当您在服务提供商中执行$this->app->bind('App\MyBundle\Contracts\ProfilerInterface','App\MyBundle\Profiles\SystemProfiler');时,您需要告诉Laravel"无论何时需要解析ProfilerInterface,都要创建一个新的SystemProfiler"。

使用该绑定设置,如果您尝试App::make('App\MyBundle\Services\ProfilerService');,Laravel将创建一个新的ProfilerService实例,并在构造函数中注入一个新的SystemProfiler实例。

但是,这并不是您想要的,因为您有ProfilerInterface的三种不同实现。你不希望Laravel总是只注射一个。在这种情况下,您将创建自定义绑定,类似于您在Symfony中所做的。

在您的服务提供中,您的绑定看起来像这样:

$this->app->bind('system_profile_service', function($app) {
    return $app->make('App\MyBundle\Services\ProfilerService', [$app->make('App\MyBundle\Profiles\SystemProfiler')]);
});

$this->app->bind('survey_profile_service', function($app) {
    return $app->make('App\MyBundle\Services\ProfilerService', [$app->make('App\MyBundle\Profiles\SurveyProfiler')]);
});

$this->app->bind('offer_profile_service', function($app) {
    return $app->make('App\MyBundle\Services\ProfilerService', [$app->make('App\MyBundle\Profiles\OfferProfiler')]);
});

现在,通过这些绑定设置,您可以在需要时从IOC解析自定义绑定。

$systemProfiler = App::make('system_profiler_service');
$surveyProfiler = App::make('survey_profile_service');
$offerProfiler = App::make('offer_profile_service');

答案 1 :(得分:2)

这里(read the docs):

// ServiceProvider
public function register()
{
    // Simple binding
    $this->app->bind('some_service.one', \App\ImplOne::class);
    $this->app->bind('some_service.two', \App\ImplTwo::class);

    // Aliasing interface - container will inject some_service.one
    // whenever interface is required...
    $this->app->alias('some_service.one', \App\SomeInterface::class);

    // ...except for the Contextual Binding:
    $this->app->when(\App\DependantTwo::class)
              ->needs(\App\SomeInterface::class)
              ->give('some_service.two');
}

USAGE:

$ php artisan tinker

// Aliases
>>> app('some_service.one')
=> App\ImplOne {#669}
>>> app('some_service.two')
=> App\ImplTwo {#671}

// Aliased interface
>>> app('App\SomeInterface')
=> App\ImplOne {#677}
>>> app('App\DependantOne')->dependency
=> App\ImplOne {#677}

// Contextual
>>> app('App\DependantTwo')->dependency
=> App\ImplOne {#676}

鉴于此设置:

namespace App;

class ImplOne implements SomeInterface {}

class ImplTwo implements SomeInterface {}

class DependantOne
{
    public function __construct(SomeInterface $dependency)
    {
        $this->dependency = $dependency;
    }
}

class DependantTwo
{
    public function __construct(SomeInterface $dependency)
    {
        $this->dependency = $dependency;
    }
}