Laravel:构建时目标不可实例化
Laravel: Target is not instantiable while building
抱歉,如果该问题重复,但我在 Whosebug 中阅读了很多相关问题,但 none 解决了我的问题:
我创建了一个有效的 Artisan 命令,我注入了一个 Kafka 客户端服务作为第一个参数和一个具体的 class,BudgetsTransformer,作为第二个参数
class ConsumeBudgetsCommand extends Command {
public function __construct(FKafka $kafkaClient, BudgetsTransformer $transformer)
{
$this->kafkaClient = $kafkaClient;
$this->transformer = $transformer;
parent::__construct();
}
}
AppServiceProvider class 看起来像:
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:
class ConsumeBudgetsCommand extends Command {
public function __construct(FKafka $kafkaClient, TransformerInterface $transformer)
{
$this->kafkaClient = $kafkaClient;
$this->transformer = $transformer;
parent::__construct();
}
}
但是当我尝试 运行 某些 artisan
命令时出现以下问题
In Container.php line 933:
Target [App\Transformers\TransformerInterface] is not instantiable while building [App\Console\Commands\ConsumeBudgetsCommand].
我 运行 以前发出以下 artisan 命令以防万一... cache:clear
、clear-compiled
、optimize
等等,但运气不好
我做错了什么?我是否应该以我现在为传递和接口而不是具体的 class 所做的不同方式绑定 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]);
});
但仍然无效,无论如何这种方法(即使有效)也无法解决问题,因为当我想添加另一个不同的转换器实现时,假设 CostTransformer
实现 TransformerInterface
总是会注入 BudgetTransformer
。所以阅读 link 中的文档,我发现 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
?
绑定接口必须使用这个结构https://laravel.com/docs/5.5/container#binding-interfaces-to-implementations
$this->app->bind(TransformerInterface::class, BudgetsTransformer::class);
和
$this->app->bind('consume:budgets', function ($app) {
return new ConsumeBudgetsCommand($app['kafka.client'], $app->make(TransformerInterface::class));
});
抱歉,如果该问题重复,但我在 Whosebug 中阅读了很多相关问题,但 none 解决了我的问题:
我创建了一个有效的 Artisan 命令,我注入了一个 Kafka 客户端服务作为第一个参数和一个具体的 class,BudgetsTransformer,作为第二个参数
class ConsumeBudgetsCommand extends Command {
public function __construct(FKafka $kafkaClient, BudgetsTransformer $transformer)
{
$this->kafkaClient = $kafkaClient;
$this->transformer = $transformer;
parent::__construct();
}
}
AppServiceProvider class 看起来像:
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:
class ConsumeBudgetsCommand extends Command {
public function __construct(FKafka $kafkaClient, TransformerInterface $transformer)
{
$this->kafkaClient = $kafkaClient;
$this->transformer = $transformer;
parent::__construct();
}
}
但是当我尝试 运行 某些 artisan
命令时出现以下问题
In Container.php line 933: Target [App\Transformers\TransformerInterface] is not instantiable while building [App\Console\Commands\ConsumeBudgetsCommand].
我 运行 以前发出以下 artisan 命令以防万一... cache:clear
、clear-compiled
、optimize
等等,但运气不好
我做错了什么?我是否应该以我现在为传递和接口而不是具体的 class 所做的不同方式绑定 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]);
});
但仍然无效,无论如何这种方法(即使有效)也无法解决问题,因为当我想添加另一个不同的转换器实现时,假设 CostTransformer
实现 TransformerInterface
总是会注入 BudgetTransformer
。所以阅读 link 中的文档,我发现 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
?
绑定接口必须使用这个结构https://laravel.com/docs/5.5/container#binding-interfaces-to-implementations
$this->app->bind(TransformerInterface::class, BudgetsTransformer::class);
和
$this->app->bind('consume:budgets', function ($app) {
return new ConsumeBudgetsCommand($app['kafka.client'], $app->make(TransformerInterface::class));
});