首页 > 解决方案 > 如何在 laravel 容器中交换依赖项

问题描述

我已经注册了一个 Paypal 服务提供商:

App\Providers\PaypalHelperServiceProvider::class,

并且,当我在控制器中输入提示时,它会正确解析:

public function refund(Request $request, PaypalHelper $paypal) {...

这是我的提供者类:

class PaypalHelperServiceProvider extends ServiceProvider
{
  protected $defer = true;

  public function register()
  {
      $this->app->bind('App\Helpers\PaypalHelper', function() {
          $test = 'test';
          return new PaypalHelper();
      });
    }

    public function provides()
    {
      $test = 'test';
      return [App\Helpers\PaypalHelper::class];
    }
  }

一切都按预期工作。现在我希望能够修改控制器以采用 PayPal 接口。然后,我将更新我的服务提供者,以有条件地传入真实类或模拟类进行测试,使用 APP_ENV 变量来确定使用哪一个。我将一些调试器放入服务提供者类中,但无法让它进入。我认为它可能只在需要时加载它们,所以我在控制器中放置了一个断点。该类确实解决了,但它仍然从未进入服务提供者类!有人可以向我解释为什么会这样吗?即使我修改了代码以传入不同的类类型,它也没有被接受。

编辑:

这是我调试时看到的代码流:ControllerDispatcher -> resolveClassMethodDependencies -> resolveMethodDependencies -> transformDependency。此时我们在 RouteDependencyResolveerTrait 中有如下 laravel 代码:

 protected function transformDependency(ReflectionParameter $parameter, $parameters, $originalParameters)
{
    $class = $parameter->getClass();

    // If the parameter has a type-hinted class, we will check to see if it is already in
    // the list of parameters. If it is we will just skip it as it is probably a model
    // binding and we do not want to mess with those; otherwise, we resolve it here.
    if ($class && ! $this->alreadyInParameters($class->name, $parameters)) {
        return $this->container->make($class->name);
    }
}

由于 getClass() 总是解析为接口名称,所以当我们调用 container->make() 时,它总是会失败

Target [App\Helpers\PaypalHelperInterface] is not instantiable.

标签: laravelcontainersservice-provider

解决方案


改变

      $this->app->bind('App\Helpers\PaypalHelper', function() {
          $test = 'test';
          return new PaypalHelper();
      });

if (app()->environment('testing')) {
    $this->app->bind(
        PaypalHelperInterface::class,
        FakePaypalHelper::class
    )
} else {
    $this->app->bind(
        PaypalHelperInterface::class,
        PaypalHelper::class
    );
}

推荐阅读