简体   繁体   English

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

[英]PHP - Laravel dependency injection: pass parameters to dependency constructor

I'm building a Laravel project and in one of the controllers I'm injecting two dependencies in a method:我正在构建一个 Laravel 项目,并且在其中一个控制器中,我在一个方法中注入了两个依赖项:

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

My question is really simple: How do I pass parameters to the $channelAuth dependency?我的问题很简单:如何将参数传递给$channelAuth依赖项?

At the moment I'm using some setters to pass the needed dependencies:目前我正在使用一些 setter 来传递所需的依赖项:

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

What are the alternatives to this approach?这种方法的替代方法是什么?

PS The code needs to be testable. PS 代码需要可测试。

Thanks to the help I received on this Laracast discussion I was able to answer this question.感谢我在这个Laracast 讨论中得到的帮助,我能够回答这个问题。 Using a service provider it's possible to initialize the dependency by passing the right parameters to the constructor.使用服务提供者可以通过将正确的参数传递给构造函数来初始化依赖项。 This is the service provider I created:这是我创建的服务提供者:

<?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());
        });
    }
}

You can pass parameters (as a string indexed array) when resolving a dependence like this:在解决这样的依赖时,您可以传递参数(作为字符串索引数组):

<?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());
        });
    }
}

Then when resolving eg in a controller:然后在例如在控制器中解析时:

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

If you want to inject the dependency through type hint you should use Factory pattern如果你想通过类型提示注入依赖,你应该使用工厂模式

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

You can create and register your own service provider and create object with constructor's requests parameters.您可以创建和注册自己的服务提供者,并使用构造函数的请求参数创建对象。

I don't know how to do this in Laravel, but in Symfony2 you can inject in your own service something like RequestStack.我不知道如何在 Laravel 中执行此操作,但是在 Symfony2 中,您可以在自己的服务中注入诸如 RequestStack 之类的东西。 It's the best way, because you have small service providers that are fully testable.这是最好的方法,因为您拥有完全可测试的小型服务提供商。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM