Альтернатива внедрения зависимостей конструктора заданий очереди Yii2

#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 этого достаточно.