【问题标题】:Injecting Interface on class (Laravel Package)在类上注入接口(Laravel 包)
【发布时间】:2016-05-04 20:32:26
【问题描述】:

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

我的界面是这样的:

interface BillerInterface
{
    public function payCash();

    public function payCreditCard();
}

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

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

    public function payCreditCard()
    {
        // Logic
    }
}

Biller类是主类,构造方法期望上面的接口,像这样:

class Biller {

    protected $gateway;

    public function __construct(BillerInterface $gateway)
    {

        $this->gateway = $gateway;
    }

    // Logic

}

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

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

似乎可以正常工作,但在尝试实例化 Biller 类时出现错误...

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

有什么线索吗?

【问题讨论】:

  • 您是否正在实例化Biller 实例?
  • 我正在我的路由文件中进行测试,基本上是尝试“新 Biller”并转储以查看其内容。
  • 是的,那行不通。只有在注入 Biller 以便由服务容器解析时,依赖项才会被注入,即 public function __construct(Biller $biller)
  • 或使用$biller = App::make('Biller')
  • 马丁,你的解决方案奏效了。我没有关注 IoC 容器上的依赖解析功能。在将类注入构造函数方法之后,我尝试在控制器中使用我的 Biller 类并且它正在工作。如何将您的答案设置为解决方案? =)

标签: laravel laravel-5


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      这就是我在我的应用程序中完成它的方式,它似乎正在工作:

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

      【讨论】:

        【解决方案4】:

        @MaGnetas答案

        我更喜欢用这种方式绑定类和接口。

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

        这有助于 IDE 找到类的路径,我们只需单击即可跳转到该类。

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

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

        那么当我们点击这个字符串时IDE就找不到class的位置了。

        【讨论】:

          猜你喜欢
          • 2023-03-23
          • 1970-01-01
          • 2017-02-02
          • 1970-01-01
          • 2013-10-22
          • 2022-12-20
          • 1970-01-01
          • 2019-04-17
          • 1970-01-01
          相关资源
          最近更新 更多