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