Как переключить зависимость на основе запроса в Laravel с помощью внедрения зависимостей?

#php #dependency-injection #laravel-8 #laravel-service-container

Вопрос:

Я хочу переключить платежный шлюз на основе запроса пользователя. Мне не нужно несколько конечных точек для каждого шлюза, поэтому я пытаюсь написать одну конечную точку, которая обрабатывает несколько платежных шлюзов. При этом я также хочу, чтобы метод controller __construct использовал внедрение зависимостей с использованием интерфейса шлюза. Проблема, с которой я сталкиваюсь, заключается в переключении созданного класса в соответствии с платежным шлюзом из запроса.

 use AppPaymentGatewayInterface

class XYZController {
  
  ...

  public __construct(PaymentGatewayInterface $payment_gateway) {
    $this->payment_gateway = $payment_gateway; //This should be a gateway instance of either Paypal, Stripe, Braintree, etc based on the $request of the user.
  }
  
  ...
}
 

Я знаю, что могу привязать интерфейс к классу в register() методе поставщика и добавить туда некоторую логику, но я вижу, что добавляю множество зависимостей интерфейса в действия контроллера, и я чувствую, что наличие логики в поставщике услуг может довольно быстро привести к беспорядку. Пример:

 ...
class AppServiceProvider extends ServiceProvider
{
  public function register()
  {
    if(request()->input('gateway') === "Paypal")
      $this->app->bind(PaymentGatewayInterface::class, PaypalGateway::class);
    else
      $this->app->bind(PaymentGatewayInterface::class, StripeGateway::class);
  }
}
 

Комментарии:

1. Может быть, сделать зависимость фабрикой? Затем создайте необходимый платежный шлюз, передав запрос gateway на фабрику?

2. Попробуйте создать прокси-реализацию для PaymentGatewayInterface, которая может перенаправлять вызов на одну из зависимостей PaymentGatewayInterface. Прокси-сервер может принять это решение на основе данных запроса (во время выполнения). Таким образом, вам не нужна фабрика, и XYZController не обращает внимания на тот факт, что может быть больше реализаций на выбор. Если PaymentGatewayProxy не может получить эти данные запроса, вам может быть лучше использовать интерфейс адаптера, который принимает тип шлюза в аргументах метода, но все равно перенаправляет запрос на PaymentGateway.