【发布时间】:2018-11-28 08:51:36
【问题描述】:
对不起,如果该问题重复,但我在 StackOverflow 中阅读了很多相关问题,但没有一个解决我的问题:
我创建了一个 Artisan 命令有效,我在其中注入了一个 Kafka 客户端服务作为第一个参数和一个具体类 BudgetsTransformer 作为第二个参数
class ConsumeBudgetsCommand extends Command {
public function __construct(FKafka $kafkaClient, BudgetsTransformer $transformer)
{
$this->kafkaClient = $kafkaClient;
$this->transformer = $transformer;
parent::__construct();
}
}
AppServiceProvider 类看起来像:
class AppServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('kafka.client', function ($app) {
return new \Weq\FKafka\FKafka();
});
$this->app->bind('budget.transformer', function ($app) {
return new BudgetsTransformer();
});
}
public function boot()
{
$this->app->bind('consume:budgets', function ($app) {
return new ConsumeBudgetsCommand($app['kafka.client'], $app['budget.transformer']);
});
$this->commands('consume:budgets');
}
}
到目前为止一切正常......然后我决定创建一个TransformerInterface,BudgedTransformer 实现(以及其他未来的变形金刚将实现它):
class BudgetsTransformer implements TransformerInterface
{
// ...
}
我更改了命令中的签名以注入接口而不是具体类:
class ConsumeBudgetsCommand extends Command {
public function __construct(FKafka $kafkaClient, TransformerInterface $transformer)
{
$this->kafkaClient = $kafkaClient;
$this->transformer = $transformer;
parent::__construct();
}
}
但是当我尝试运行一些 artisan 命令时出现以下问题
在 Container.php 第 933 行: 目标 [App\Transformers\TransformerInterface] 在构建 [App\Console\Commands\ConsumeBudgetsCommand] 时不可实例化。
我以前运行以下工匠命令以防万一...cache:clear、clear-compiled、optimize 等等,但没有运气
我做错了什么?我应该以我现在正在做的不同方式绑定BudgetTransformer 来传递和接口而不是具体类吗?
提前感谢您的帮助
更新
正如@davit 建议的那样,我添加了
$this->app->bind(TransformerInterface::class, BudgetsTransformer::class);
在 AppServiceProvider::register() 中,我删除了
$this->app->bind('budget.transformer', function ($app) {
return new BudgetsTransformer();
});
那里,然后我在 AppServiceProvider::boot() 中更新命令绑定:
$this->app->bind('consume:budgets', function ($app) {
return new ConsumeBudgetsCommand($app['kafka.client'], $app[TransformerInterface::class]);
});
但仍然无法正常工作,无论如何这种方法(甚至可以工作)都无法解决问题,因为当我想添加另一个不同的转换器实现时,假设实现 TransformerInterface 的 CostTransformer 将始终注入 BudgetTransformer。所以阅读链接中的文档,我发现Contextual Binding 可能是解决方案,所以我支持:
$this->app
->when(ConsumeBudgetsCommand::class)
->needs(TransformerInterface::class)
->give(function ($app) {
return new BudgetsTransformer();
});
因此,通过注入接口,我将能够将不同的转换器实现注入到不同的命令中。但还是不行。
谁能告诉我如何准确地声明命令绑定
$this->app->bind('consume:budgets', function ($app) {
return new ConsumeBudgetsCommand($app['kafka.client'], ???);
});
使用Contextual binding?
【问题讨论】:
-
您不需要任何
$this->app->bind(...,因为您的应用程序不使用它们中的任何一个来创建ConsumeBudgetsCommand对象。您只需要将TransformerInterface绑定到BudgetTransformer,以便应用知道注入它然后执行命令。
标签: php laravel laravel-artisan service-provider