【问题标题】:Laravel: Target is not instantiable while buildingLaravel:目标在构建时不可实例化
【发布时间】: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');
    }
}

到目前为止一切正常......然后我决定创建一个TransformerInterfaceBudgedTransformer 实现(以及其他未来的变形金刚将实现它):

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: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]);
});

但仍然无法正常工作,无论如何这种方法(甚至可以工作)都无法解决问题,因为当我想添加另一个不同的转换器实现时,假设实现 TransformerInterfaceCostTransformer 将始终注入 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


【解决方案1】:

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

【讨论】:

  • @Averias 你试试这个吗??
  • 是的@Davit,我试过了,请阅读我对上述问题的更新
  • 同上:目标 [App\Transformers\TransformerInterface] 在构建 [App\Console\Commands\ConsumeBudgetsCommand] 时不可实例化。
  • 你为什么要绑定?? laravel 必须自动绑定它。您是否在命令中使用 protected $signature = 'consume:budgets'??;
  • 我想绑定命令,因为我正在注入 Kafka 服务(作为命令中的第一个参数)。无论如何,甚至删除命令的绑定: $this->app->bind('consume:budgets',.... 以及命令声明: $this->commands('consume:budgets'); 它没有' t 工作(同样的错误),老实说,我想知道如何使用这两种绑定,因为它可能是我将在不久的将来面临的一个用例
猜你喜欢
  • 2019-07-05
  • 2022-10-16
  • 2015-06-07
  • 2016-06-22
  • 2013-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
相关资源
最近更新 更多