PHP - Laravel 依赖注入:向依赖项构造函数传递参数

31

我正在构建一个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());

有没有其他方法可以替代这种方法?

另外,代码必须可测试。

3个回答

32

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

<?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
但是如果您的输入没有设置'channel_name'怎么办?在验证输入之前,可能会调用此代码。 - omarjebari
@omarjebari 我猜这取决于你在哪里注入 Bloom\Security\ChannelAuthInterface,在我的情况下是在输入验证之后。 - siannone
我正在寻找类似的东西。有没有一种方法可以在控制台/artisan输入中完成这个,而不是HTTP请求? - Mathew Paret
@MathewParet 我想原则是一样的。你只需要找出你想要绑定的接口,并返回一个实现该接口的类的实例,其中包含你的更改。 - siannone

2
您可以像这样传递参数(作为字符串索引数组)来解析依赖项:
<?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 ...
}

0

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

我不知道如何在Laravel中做到这一点,但在Symfony2中,你可以注入自己的服务,比如RequestStack。这是最好的方式,因为你有小型的服务提供者,可以完全进行测试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接