在 class 上注入接口(Laravel 包)

Injecting Interface on class (Laravel Package)

我正在开发自己的 L5 包来处理付款。为了将来能够更改支付网关,我正在使用接口。

我的界面是这样的:

interface BillerInterface
{
    public function payCash();

    public function payCreditCard();
}

我也有一个具体的实现,就是想要的支付网关

class Paypal implements BillerInterface
{
    public function payCash()
    {
        // Logic
    }

    public function payCreditCard()
    {
        // Logic
    }
}

Biller class 是主要的 class,构造函数方法需要上述接口,如下所示:

class Biller {

    protected $gateway;

    public function __construct(BillerInterface $gateway)
    {

        $this->gateway = $gateway;
    }

    // Logic

}

最后,我创建了服务提供者,将接口绑定到网关 class。

public function register()
{
    $this->app->bind(BillerInterface::class, 'Vendor\Biller\Gateways\Paypal');
}

似乎可以正常工作,但我在尝试实例化 Biller 时遇到错误 class...

Biller::__construct() must be an instance of Vendor\Biller\Contracts\BillerInterface, none given

我尝试了以下代码,但似乎不起作用...

public function register()
{
    $this->app->bind(BillerInterface::class, 'Vendor\Biller\Gateways\Paypal');

    $this->app->bind(Biller::class, function ($app) {
        return new Biller($app->make(BillerInterface::class));
    });
}

有什么线索吗?

当您将接口绑定到实际 class 时,请尝试将 BillerInterface::class 替换为字符串“\Your\Namespace\BillerInterface”

这是我在我的应用程序中完成的方法,它似乎有效:

public function register()
{
    $this->app->bind('DesiredInterface', function ($app) {
        return new DesiredImplementationClass(
            $app['em'],
            new ClassMetaData(DesiredClass::class)
        );
    });
}

您正在将接口绑定到服务提供商中的实现。但是依赖只会被服务容器解决,即

class SomeClass
{
    public function __construct(Billing $billing)
    {
        $this->billing = $billing;
    }
}

Laravel 的服务容器将读取构造方法参数的类型提示,并解析该实例(以及它的任何依赖项)。

您将无法直接“新建”Billing 实例(即 $billing = new Billing),因为构造函数期望实现 BillingInterface,而您没有提供。

谈论 @MaGnetas 回答

我更喜欢使用这种方式将 class 与界面绑定。

public function register()
{
    $this->app->bind(AppointmentInterface::class, AppointmentService::class);
}

这有助于 IDE 找到 class 的路径,我们只需单击它就可以跳转到 class。

如果我们将 class 路径作为字符串路径传递,如下所示:

public function register()
{
    $this->app->bind('App\Interfaces\AppointmentInterface', 'App\Services\AppointmentService');
}

然后IDE在我们点击这个字符串的时候找不到class的位置