Laravel: цель не создается при строительстве

Извините, если этот вопрос повторяется, но я прочитал много связанных вопросов в Stackru, но никто не решил мою проблему:

Я создал команду Artisan, которая работала, и где я внедрил клиентскую службу Kafka в качестве 1-го параметра и конкретный класс, BudgetsTransformer, в качестве 2-го параметра

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 команда

В строке 933 Container.php: цель [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]);
});

Но все еще не работает, в любом случае этот подход (даже рабочий) не решит проблему, так как, когда я хочу добавить другую реализацию преобразователя, скажем, CostTransformer который реализует TransformerInterface всегда будет вводить BudgetTransformer, Так что читая документацию по ссылке, я обнаружил, что Contextual Binding может быть решением, поэтому я sustituded по:

$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?

1 ответ

Решение

Для привязки интерфейсов необходимо использовать эту структуру https://laravel.com/docs/5.5/container

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

А также

$this->app->bind('consume:budgets', function ($app) {
    return new ConsumeBudgetsCommand($app['kafka.client'], $app->make(TransformerInterface::class));
});
Другие вопросы по тегам