Laravel: контроллер или промежуточное ПО - PullRequest
1 голос
/ 11 апреля 2020

Я использую Laravel 6.9.0. Это мой контроллер платежей:

class PaymentController extends Controller
{
    public function __construct(){
        $this->middleware('payment.test');
        $this->middleware('payment.check');
    }

    public function pay(){
        $this->payment->pay();
    }

    public function refund(){
        $this->payment->refund();
    }

    public function checkOrder(){
        $this->payment->checkOrder();
    }
}

Промежуточное программное обеспечение payment.test выполняет следующие действия:

  1. журнал запросов на запись
  2. проверяет, существует ли продавец
  3. расшифровать реквизит

Промежуточное программное обеспечение payment.check используется для проверки того, какой платеж, например, applepay или googlelpay.

Но из официальной документации промежуточное программное обеспечение используется для фильтрации HTTP запрашивает, проверяет подлинность пользователя вашего приложения.

Кажется, payment.check не относится к этому. Таким образом, я заменяю промежуточное ПО payment.check на контроллер. Поскольку все методы должны проверять платеж, я помещаю его в конструктор. Однако я должен расшифровать запрос перед тем, как его проверить, поэтому мой конструктор теперь

$this->middleware('payment.test');

$this->middleware(function ($request, $next) {
    $this->checkPayment($request);

    return $next($request);
});

checkPayment выглядит так:

private function checkPayment($request){
    if($request->aaa == 'aaa'){
        switch($request->type){
            case '001':
                $type = 'apple';
                break;
            case '111':
                $type = 'google';
                break;
            ...

        }
    }else{
        switch($request->code){
            case 'android':
                $type = 'android';
                break;
            ...
        }
    }


    $this->payment = app($type);
}

Это делает мой контроллер уродливым. Я чувствую, что запись в промежуточное ПО выглядит более модульной и понятной. Действительно ли запись в контроллер лучше, чем в промежуточном программном обеспечении? Или какие-либо другие предложения?

1 Ответ

0 голосов
/ 12 апреля 2020

Как я понимаю, вся ваша проблема в том, чтобы создать правильную реализацию, даже если ваша логика c делает это в конце, вызывая $this->payment = app($type);. Основная концепция все еще в этом контексте, какой поставщик вам нужен. Есть много вариантов для этого, сервис, фабрика и др. c. но сделать эту версию для контейнерного провайдера действительно мощно и чисто, когда вы находитесь в Laravel.

Представьте, что у вас есть PaymentProviderInterface, я бы связал это, чтобы решить, какого поставщика платежей использовать. Объедините это с тем, что вы в любом контексте можете разрешить объект запроса, и вы можете переместить все это поставщику, я бы создал новый. PaymentProvider и зарегистрируйте его как любого другого провайдера.

class PaymentsProvider {
    public const APPLE_PAYMENT_PROVIDER = 'apple';

    public const GOOGLE_PAYMENT_PROVIDER = 'google';

    public const ANDROID_PAYMENT_PROVIDER = 'android';

    public function boot() {
        $this->app->bind(PaymentProviderInterface::class, function () {
           /** @var Request $request **/
           $request = resolve(Request::class);

           $type = null;

           if($request->aaa == 'aaa') {
               $type = $this->resolvePaymentByType($request->type);
           } else {
               $type = $this->resolvePaymentByCode($request->code);
           }

           return resolve($type);
        });
    }

    private function resolvePaymentByType(string $type): string
    {
        if ($type === '001') {
            return static::APPLE_PAYMENT_PROVIDER;
        }

        if ($type === '111') {
            return static::GOOGLE_PAYMENT_PROVIDER;
        }

        throw new Exception('Invalid state');
    }

    private function resolvePaymentByCode(string $code): string
    {
        if ($type === static::ANDROID_PAYMENT_PROVIDER) {
            return static::ANDROID_PAYMENT_PROVIDER;
        }

        throw new Exception('Invalid state');
    }
}

В общем, я не люблю переключать случаи, вы можете использовать их, если хотите, я думаю, что это более чисто. Еще одна небольшая оптимизация, вместо использования констант magi c с использованием констант, она более читабельна и имеет большой потенциал роста. Так как мы связали все с PaymentProviderInterface, это сделало бы ваш контроллер действительно чистым, решив вашего провайдера следующим образом. Чтобы избежать условий, когда у вас нет запроса, я бы вводил в каждый метод.

class PaymentController extends Controller
{
    public function pay(PaymentProviderInterface $payment){
        $payment->pay();
    }
...