将接口绑定到 Laravel5 服务提供商中的构造具体 class

Binding an interface to a constructed concrete class in a Laravel5 service provider

我有一个接口,我想绑定到一个具体的 class。问题是,具体 class 在实例化时需要一些配置项。这是我所做的:

...

class FileMakerServiceProvider extends ServiceProvider
{
    public function boot()
    {
        //
    }

    public function register()
    {
        $this->app->bind('FileMakerInterface', function ($app){
            $username = env('FM_USERNAME');
            $password = env('FM_PASSWORD');
            $host     = env('FM_HOST');
            $database = env('FM_DATABASE');

            return new SSCSimpleFm(compact('username', 'password', 'host', 'database'));
        });
    }
}

我正在获取我需要的配置项,然后传入一个新建的混凝土 class。

问题是当我尝试将接口注入我的开发控制器进行测试时:

...

use App\Services\FileMakerInterface;

class DevController extends Controller
{

    public function testFmConnect(FileMakerInterface $fm){
        return $fm;
    }
}

我收到接口不可实例化的错误:

而且我肯定在 config/app.php 中包含了我的服务提供商:

     /*
     * Application Service Providers...
     */
    App\Providers\AppServiceProvider::class,
    App\Providers\EventServiceProvider::class,
    App\Providers\RouteServiceProvider::class,

    App\Providers\FileMakerServiceProvider::class

我知道可以像这样在我的服务提供商中绑定 classes:

public function register()
{
    $this->app->bind('FileMakerInterface', 'SSCSimpleFm');
}

但如果我那样做,我就无法注入凭据。

我在这里错过了什么?

您只是将具体 class 绑定到 FileMakerInterface。它需要一个完全限定的命名空间:

$this->app->bind('App\Services\FileMakerInterface', function ($app) {
    return new SSCSimpleFm([
        'host'     => env('FM_HOST'),
        'username' => env('FM_USERNAME'),
        'password' => env('FM_PASSWORD'),
        'database' => env('FM_DATABASE'),
    ]);
}

现在,当您键入提示 App\Services\FileMakerInterface 时,您将获得绑定 class 的实例。