PHP - Laravel依赖注入:将参数传递给依赖构造函数

时间:2015-04-17 12:24:04

标签: php dependency-injection

我正在构建一个Laravel项目,并且在一个控制器中,我在一个方法中注入了两个依赖项:

public function pusherAuth(Request $request, ChannelAuth $channelAuth) { ... }

我的问题很简单:如何将参数传递给$channelAuth依赖项?

目前我正在使用一些setter传递所需的依赖项:

public function pusherAuth(Request $request, ChannelAuth $channelAuth)
{
    $channelAuth
        ->setChannel($request->input('channel'))
        ->setUser(Auth::user());

这种方法有哪些替代方案?

P.S。代码需要是可测试的。

4 个答案:

答案 0 :(得分:15)

感谢我在Laracast discussion收到的帮助,我能够回答这个问题。使用服务提供程序,可以通过将正确的参数传递给构造函数来初始化依赖项。这是我创建的服务提供商:

<?php namespace App\Providers;

use Security\ChannelAuth;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;

class ChannelAuthServiceProvider extends ServiceProvider {

    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('Bloom\Security\ChannelAuthInterface', function()
        {
            $request = $this->app->make(Request::class);
            $guard   = $this->app->make(Guard::class);

            return new ChannelAuth($request->input('channel_name'), $guard->user());
        });
    }
}

答案 1 :(得分:0)

您可以创建和注册自己的服务提供商,并使用构造函数的请求参数创建对象。

我不知道如何在Laravel中执行此操作,但在Symfony2中,您可以在自己的服务中注入类似RequestStack的内容。这是最好的方式,因为您拥有完全可测试的小型服务提供商。

答案 2 :(得分:0)

如果要通过类型提示注入依赖项,则应使用Factory模式

public function pusherAuth(Request $request, ChannelAuthFactory $channelAuthFactory)
{
    $channelAuth = $channelAuthFactory->from($request->input('channel'), $request->user());

答案 3 :(得分:0)

在解决这种依赖性时,您可以传递参数(作为字符串索引数组):

<?php namespace App\Providers;

use Security\ChannelAuth;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Support\ServiceProvider;

class ChannelAuthServiceProvider extends ServiceProvider {

    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('Bloom\Security\ChannelAuthInterface', function($params)
        {
            $channelName = $params['channelName'];
            $guard   = $this->app->make(Guard::class);

            return new ChannelAuth($channelName, $guard->user());
        });
    }
}

然后在控制器中解析时:

public function pusherAuth()
{
    $channelAuth = app()->makeWith('Bloom\Security\ChannelAuthInterface', [
        'channelName' => $request->input('channel_name')
    ]);
    // ... use $channelAuth ...
}