Laravel:在构建时无法实例化目标 [英] Laravel: Target is not instantiable while building

查看:673
本文介绍了Laravel:在构建时无法实例化目标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很抱歉,如果该问题重复,但是我在StackOverflow中阅读了很多相关问题,但没有一个解决了我的问题:

Sorry if that question is duplicate, but I've read a lot of related question in StackOverflow but none solved my problem:

我创建了一个Artisan命令,该命令有效,并在其中注入了Kafka客户服务作为第一个参数,并注入了具体类BudgetsTransformer作为第二个参数

I created an Artisan command which worked and where I injected a Kafka client service as 1st param and a concrete class, BudgetsTransformer, as the 2nd parameter

class ConsumeBudgetsCommand extends Command {
    public function __construct(FKafka $kafkaClient, BudgetsTransformer $transformer)
    {
        $this->kafkaClient = $kafkaClient;
        $this->transformer = $transformer;

        parent::__construct();
    }
}

AppServiceProvider类如下:

AppServiceProvider class looked like:

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也会实现):

So far all is working properly... Then I decided to create a TransformerInterface which BudgedTransformer implements (and other future Transformers will implement it):

class BudgetsTransformer implements TransformerInterface
{
 // ...
}

我更改了命令中的签名以注入接口,而不是具体的类:

and I changed the signature in the command to inject the interface instead of the concrete class:

class ConsumeBudgetsCommand extends Command {
    public function __construct(FKafka $kafkaClient, TransformerInterface $transformer)
    {
        $this->kafkaClient = $kafkaClient;
        $this->transformer = $transformer;

        parent::__construct();
    }
}

但是当我尝试运行一些artisan命令

But I get the following issue when I try to run some artisan command

在Container.php第933行中: 构建[App \ Console \ Commands \ ConsumeBudgetsCommand]时,无法实例化目标[App \ Transformers \ TransformerInterface].

In Container.php line 933: Target [App\Transformers\TransformerInterface] is not instantiable while building [App\Console\Commands\ConsumeBudgetsCommand].

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

I run previously the issue the following artisan command just in case... cache:clear, clear-compiled, optimize and so on but no luck

我做错了什么?我应该用现在为传递和接口而不是具体的类采用的其他方式绑定BudgetTransformer吗?

What I'm doing wrong? Should I bind the BudgetTransformer in a different way I'm doing now for passing and Interface instead of a concrete class?

预先感谢您的帮助

更新

按照@davit的建议,我添加了

As @davit suggested, I added

$this->app->bind(TransformerInterface::class, BudgetsTransformer::class);

在AppServiceProvider :: register()中,我删除了

in AppServiceProvider::register() and I removed

$this->app->bind('budget.transformer', function ($app) {
        return new BudgetsTransformer();
});

在那里,然后在AppServiceProvider :: boot()中更新命令绑定:

there, then I update in AppServiceProvider::boot() the command binding:

$this->app->bind('consume:budgets', function ($app) {
        return new ConsumeBudgetsCommand($app['kafka.client'], $app[TransformerInterface::class]);
});

但是仍然无法正常工作,无论如何,这种方法(即使可行)也无法解决问题,因为当我想添加另一个不同的转换器实现时,假设实现了TransformerInterfaceCostTransformer总是会注入BudgetTransformer.因此,阅读链接中的文档后,我发现Contextual Binding可能是解决方案,所以我对此表示怀疑:

But still not working, anyway this approach (even working) will not resolve the issue since when I want to add another different transformer implementation, let's say CostTransformer which implements TransformerInterface is gonna always inject BudgetTransformer. So reading the documentation in the link, I found that Contextual Binding could be the solution, so I sustituded by:

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

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

So in that way, I will be able to inject different implementations of transformers to different commands by injecting the interface. But still not working.

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

Can someone tell me how exactly declare the command binding

$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

For binding interfaces must be use this structure 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));
});

这篇关于Laravel:在构建时无法实例化目标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆