Laravel:在构建时无法实例化目标

时间:2018-06-19 11:42:57

标签: php laravel artisan service-provider

很抱歉,如果该问题重复,但是我在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(其他将来的Transformers也会实现):

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 \ Console \ Commands \ ConsumeBudgetsCommand]时,无法实例化目标[App \ Transformers \ TransformerInterface]。

我以前会运行以下工匠命令,以防万一... cache:clearclear-compiledoptimize等,但是没有运气

我做错了什么?我应该用一种现在传递和接口而不是具体类的方式绑定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的{​​{1}}总是会注入{ {1}}。因此,阅读链接中的文档后,我发现TransformerInterface可能是解决方案,所以我对此感到怀疑:

BudgetTransformer

因此,通过这种方式,我将能够通过注入接口将转换器的不同实现注入不同的命令。但仍然无法正常工作。

有人可以告诉我如何精确声明命令绑定

Contextual Binding

使用那个$this->app ->when(ConsumeBudgetsCommand::class) ->needs(TransformerInterface::class) ->give(function ($app) { return new BudgetsTransformer(); });

1 个答案:

答案 0 :(得分:2)

对于绑定接口,必须使用此结构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));
});