#dependency-injection #yii2
#внедрение зависимостей #yii2
Вопрос:
Мне нужно получить зависимости в классе, который реализует интерфейс yii queue Job. В идеальном мире я бы сделал что-то вроде этого:
public function __construct(SomeInterface $service)
{
$this->service = $service;
}
public function execute($queue)
{
$this->service->doSomething();
}
К сожалению, yii2-queue не поддерживает разрешение зависимостей в конструкторе обработчика заданий. На данный момент я разбираюсь с этим следующим образом:
public function execute($queue)
{
$service = Yii::$container->get(SomeInterface::class);
$service->doSomething();
}
Может быть, есть более чистый способ сделать это?
Комментарии:
1. Можете ли вы создать свой класс заданий с помощью
Yii::createObject()
?
Ответ №1:
Я разобрался с этим, используя шаблон заводского метода и разрешая зависимости из контейнера DI в нем. Хотя есть некоторые проблемы с сериализацией тяжелых зависимостей. Чтобы решить эту проблему, я использовал простой прокси.
$this->queue->push(FooJob::create($someId));
// (...)
class FooJob implements Job
{
public $id;
private $fooService;
private $heavyService;
public function __construct(int $id, FooInterface $fooService)
{
$this->fooService = $fooService;
}
public static function create(int $id): self
{
return Yii::$container->get(static::class, [$id]);
}
public function execute(Queue $queue): void
{
$this->fooService->bar($this->id); // service available since construct
$this->heavyService->bark($this->id); // service available since first call
}
public function getHeavyService(Queue $queue): HeavyInterface
{
if (!$this->heavyService) {
$this->heavyService = Yii::$container->get(HeavyServiceInterface::class);
}
return $this->heavyService;
}
}
Это более чистый подход, чем тот, который я использовал раньше. Это не идеально, но с ограничениями Yii этого достаточно.