如何换出 laravel 容器中的依赖项
How to swap out dependency in laravel container
我已经注册了一个Paypal服务商:
App\Providers\PaypalHelperServiceProvider::class,
并且,当我在我的控制器中键入提示时,它会正确解析:
public function refund(Request $request, PaypalHelper $paypal) {...
这是我的提供商 class:
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 接口。然后我会更新我的服务提供商以有条件地传递真实的 class 或模拟的用于测试,使用 APP_ENV 变量来确定使用哪一个。我将一些调试器放入服务提供者 class 中,但无法让它进入。我认为它可能只在需要时加载它们,所以我在我的控制器中放置了一个断点。 class 确实解决了,但它仍然没有进入服务提供商 class!有人可以向我解释为什么会这样吗?即使我修改了代码以传入不同的 class 类型,它也没有接收到。
编辑:
这是我在调试时看到的代码流:
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.
改变
$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
);
}
我终于找到问题所在了。我的问题是我的提供者根本没有被接走。这是解决方案
composer dumpautoload
php artisan cache:clear
https://laravel.io/forum/02-08-2015-laravel-5-service-provider-not-working
我已经注册了一个Paypal服务商:
App\Providers\PaypalHelperServiceProvider::class,
并且,当我在我的控制器中键入提示时,它会正确解析:
public function refund(Request $request, PaypalHelper $paypal) {...
这是我的提供商 class:
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 接口。然后我会更新我的服务提供商以有条件地传递真实的 class 或模拟的用于测试,使用 APP_ENV 变量来确定使用哪一个。我将一些调试器放入服务提供者 class 中,但无法让它进入。我认为它可能只在需要时加载它们,所以我在我的控制器中放置了一个断点。 class 确实解决了,但它仍然没有进入服务提供商 class!有人可以向我解释为什么会这样吗?即使我修改了代码以传入不同的 class 类型,它也没有接收到。
编辑:
这是我在调试时看到的代码流: 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.
改变
$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
);
}
我终于找到问题所在了。我的问题是我的提供者根本没有被接走。这是解决方案
composer dumpautoload
php artisan cache:clear
https://laravel.io/forum/02-08-2015-laravel-5-service-provider-not-working