Как использовать связанную реализацию в Laravel Job Class? - PullRequest
1 голос
/ 16 мая 2019

Я бы использовал интерфейс в моих работах и ​​получил бы контекстную реализацию его в классах Джобса.

Я читаю все туты.

Я регистрирую это:

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app
            ->when(SendinBlueJob::class)
            ->needs(MessageProviderInterface::class)
            ->give(SendinBlueService::class);
    }
}

Я отправляю задание:

class MessageObserver
{
    public function created(MessageInterface $message)
    {
        SendinBlueJob::dispatch($message);
    }
}

В рабочем классе я хочу получить привязанный сервис:

class SendinBlueJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

     public $message;
     public $messageProvider;

    public function __construct(MessageInterface $message, MessageProviderInterface $messageProvider)
    {
        $this->message = $message;
        $this->messageProvider = $messageProvider;
        $this->handle();
     }

    public function handle()
    {
        dd($this->messageProvider);
    }
}

Я не могу отправить задание, потому что сервер выдает ошибку:

Слишком мало аргументов для функции App \ Jobs \ SendinBlueJob :: __ construct (), 1 прошло в /var/www/vendor/laravel/framework/src/Illuminate/Foundation/Bus/Dispatchable.php в строке 16 и ровно 2 ожидается

Я понимаю, но не понимаю, почему Laravel не внедряет службу с привязкой, если интерфейс вызывается в конструкторе.

1 Ответ

2 голосов
/ 16 мая 2019

Вы можете внедрить зависимости в методе handle.

class SendinBlueJob implements ShouldQueue
{
    use Dispatchable,
        InteractsWithQueue,
        Queueable,
        SerializesModels;

    public $message;

    public function __construct(MessageInterface $message)
    {
        $this->message = $message;
    }

    public function handle(MessageProviderInterface $messageProvider)
    {
        dd(
            $this->message, // MessageInterface
            $messageProvider // SendInBlueService
        );
    }
}

Обновление

Раствор 1

Поскольку вы используете контекстную привязку, а контекстная привязка не работает, когда вы вводите зависимости с помощью метода (который является единственным способом сделать это в работе), рассмотрите следующий подход ...

У вашего поставщика услуг:

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->when(MessagesController::class) // Your controller
                  ->needs(MessageProviderInterface::class)
                  ->give(SendinBlueService::class);
    }
}

В вашем контроллере:

class MessagesController extends Controller
{
    protected $messageProvider;

    public function __construct(MessageProviderInterface $messageProvider)
    {
        $this->messageProvider = $messageProvider;
    }

    public function store(Request $request)
    {
        // ...

        // Create your message
        $message = Message::create($request->all());

        // Dispatch your job in the controller
        SendInBlueJob::dispatch($message, $this->messageProvider);

        // ...
    }
}

В вашей работе:

class SendinBlueJob implements ShouldQueue
{
    use Dispatchable,
        InteractsWithQueue,
        Queueable,
        SerializesModels;

    protected $message;

    protected $messageProvider;

    public function __construct(MessageInterface $message, MessageProviderInterface $messageProvider)
    {
        $this->message = $message;

        $this->messageProvider = $messageProvider;
    }

    public function handle()
    {
        dd($this->messageProvider);
    }
}

Раствор 2

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

Создать новый SendinBlueMessageProviderInterface:

interface SendinBlueMessageProviderInterface extends MessageProviderInterface
{
    //
}

Свяжите интерфейс с вашей реализацией.

$this->app->bind(
    SendinBlueMessageProviderInterface::class,
    SendinBlueService::class
);

Теперь вы сможете внедрить поставщика сообщений с помощью метода handle.

public function handle(SendinBlueMessageProviderInterface $messageProvider)
{
    dd($messageProvider);
}
...