[Laravel]: Как добавить зависимость в абстрактный класс, расширенный другими классами (заданиями) - PullRequest
0 голосов
/ 03 сентября 2018

У меня есть проект Laravel, в котором я создал абстрактный класс, который будет использовать несколько моих заданий, поскольку всем им нужно использовать один и тот же метод для поиска некоторых данных.

В Laravel способ работы заданий заключается в том, что конструктор принимает любые значения, с которыми вы запускаете задание, и в методе-обработчике можно вставлять зависимости, например:

class SomeJob extends Job implements ShouldQueue
{
    public function __construct(array $someData, int $someMoreData)
    {
        $this->someData     = $someData;
        $this->someMoreData = $someMoreData;
    }

    public function handle()
    {
        // Do something...
    }
}


\Queue::pushOn(Queue::getDefaultQueue(), new SomeJob([1, 2, 3], 4));

Это означает, что я не могу просто передать зависимости в абстрактный класс из конструктора расширяющегося класса. Единственный способ обойти это, как я вижу, - это иметь свойство в абстрактном классе, а затем установить его в методе обработчика расширенного класса.

abstract class SomeAbstractClass extends Job implements ShouldQueue
{
    use InteractsWithQueue, SerializesModels;

    protected $configOne;
    protected $configTwo;
    protected $userRepository;

    public function __construct()
    {
        $this->configOne = config('someConfig.valueOne');
        $this->configTwo = config('someConfig.valueTwo');
    }

    public function doSomethingWithUserRepository()
    {
        return $this->userRepository->doSomething();
    }
}

class SomeClass extends SomeAbstractClass
{
    public function __construct(array $someData, int $someMoreData)
    {
        parent::__construct();

        $this->someData     = $someData;
        $this->someMoreData = $someMoreData;
    }

    public function handle(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }
}

Это работает как задумано, но не похоже на правильный способ сделать это. Это кажется немного хакерским, даже если это работает. Есть ли способ обойти это? Это должно быть у него довольно распространенная проблема, в том числе за пределами Laravel.

1 Ответ

0 голосов
/ 04 сентября 2018

Поскольку определенный конструктор используется для доставки данных в задания в Laravel, поэтому в этом случае вы должны трактовать handle() как метод "конструктор".

Итак, рассмотрим этот пример:

<?php
abstract class SomeAbstractClass extends Job implements ShouldQueue
{
    use InteractsWithQueue, SerializesModels;

    protected $configOne;
    protected $configTwo;
    protected $userRepository;

    public function __construct()
    {
        $this->configOne = config('someConfig.valueOne');
        $this->configTwo = config('someConfig.valueTwo');
    }

    public function handle(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    protected function doSomethingWithUserRepository()
    {
        return $this->userRepository->doSomething();
    }
}

class SomeClass extends SomeAbstractClass
{
    public function __construct(array $someData, int $someMoreData)
    {
        parent::__construct();
        $this->someData     = $someData;
        $this->someMoreData = $someMoreData;
    }

    public function handle(UserRepository $userRepository)
    {
        parent::handle($userRepository);

        // you can do whatever you liiike
        $this->doSomethingWithUserRepository();
    }
}
...