为了账号安全,请及时绑定邮箱和手机立即绑定

Laravel 同时处理来自 API 和表单的请求的最佳策略

Laravel 同时处理来自 API 和表单的请求的最佳策略

PHP
Qyouu 2023-07-08 15:44:54
使用 Laravel 7.*,我的任务是创建一个简单的应用程序来发送付款请求,用户填写表单并发送数据,然后验证用户输入并创建一个新的 Payment 实例。然后用户被重定向回同一页面。(当然还有其他要求列出所有付款并更新付款):   //In PaymentController.php   public function store()    {        $inputData = $this->validateRequest();        $person = $this->personRepository->findOneByAttribute('id_number', request('id_number'));        if ($person instanceof Person) {            $this->paymentRepository->create($inputData, $person);            return back()->with('successMessage', 'Your payment request registered successfully.');        } else {            return back()->with('failureMessage', 'Shoot! Cannot find a peron with the given Identification Number.')->withInput();        }    }一切都很好,但我需要实现一个 Restful API 来执行相同的请求并获得有效的 json 响应,假设没有前端 JavaScript 框架,实现此目标的最佳方法是什么?我应该创建一个单独的控制器吗?或者简单地检查请求是从传统表单还是API客户端发送的?我错过了设计模式吗?
查看完整描述

2 回答

?
慕森卡

TA贡献1806条经验 获得超8个赞

最简单的方法是检查您应该发回什么样的响应:


   //In PaymentController.php


   public function store()

    {

        $inputData = $this->validateRequest();


        $person = $this->personRepository->findOneByAttribute('id_number', request('id_number'));


        if ($person instanceof Person) {

            $this->paymentRepository->create($inputData, $person);

            if (request()->expectsJson()) {

                return response('', 201); // Just a successfully created response 

            }

            return back()->with('successMessage', 'Your payment request registered successfully.');

        } else {

            if (request()->expectsJson()) {

                return response()->json([ 'error' => 'Not found' ], 404); // You can change the error code and message (or remove the message) as needed

            }

            return back()->with('failureMessage', 'Shoot! Cannot find a person with the given Identification Number.')->withInput();

        }

    }

Responsible您当然可以选择将其封装在实现该接口的类中


class PaymentResponse implements Responsible {

     private $success;

     public function __construct($success) {

           $this->success = $success;

     }


     public function toResponse($request) {

         if ($this->success) {

            if (request()->expectsJson()) {

                return response()->json([ 'error' => 'Not found' ], 404); // You can change the error code and message (or remove the message) as needed

            }

            return back()->with('failureMessage', 'Shoot! Cannot find a person with the given Identification Number.')->withInput();

          } 

          if (request()->expectsJson()) {

              return response()->json([ 'error' => 'Not found' ], 404); // You can change the error code and message (or remove the message) as needed

          }

          return back()->with('failureMessage', 'Shoot! Cannot find a person with the given Identification Number.')->withInput();

     }

  

}

那么你的代码将是:


//In PaymentController.php


   public function store()

    {

        $inputData = $this->validateRequest();


        $person = $this->personRepository->findOneByAttribute('id_number', request('id_number'));


        if ($person instanceof Person) {

            $this->paymentRepository->create($inputData, $person);

            return new PaymentResponse(true);

        } else {

            return new PaymentResponse(false);

        }

    }

当然,您也可以将控制器逻辑提取到单独的库中,然后拥有两个单独的控制器方法,并且如果需要,仍然可以使用负责的对象。这实际上取决于您的用例以及最适合您的方法


查看完整回答
反对 回复 2023-07-08
?
一只名叫tom的猫

TA贡献1906条经验 获得超2个赞

我认为另一种方法是利用服务存储库模式。您将应用程序服务包装在一个单独的类中。服务是控制器和存储库之间的交互器。流程看起来像[request] -> [controller] -> [service] -> [repository]。


通过利用此模式,您可以在应用程序的不同区域重复使用您的服务。例如,您可以拥有一个专门用于服务传统 Web 应用程序的控制器,以及一个通过返回 JSON 数据来服务 SPA 的控制器,但服务相同的业务流程。


例如:


付款回复:


class PaymentStoreResponse

{

    protected $message;

    protected $code;

    protected $extraData;


    public function __construct($message, $code, $extraData = "")

    {

        $this->message = $message;

        $this->code = $code;

        $this->extraData = $extraData;

    }


    public function getMessage()

    {

        return $this->message;

    }


    public function getCode()

    {

        return $this->code;

    }

    

    public function getExtraData()

    {

        return $this->extraData;

    }

}

付款服务:


function store($data)

{

    $person = $this->personRepository->findOneByAttribute('id_number', $data('id_number'));


    if ($person instanceof Person) {

        $this->paymentRepository->create($inputData, $person);

        return new PaymentResponse("paymentSuccess", 201, "successMessage");

    } else {

        return new PaymentResponse("notFound", 404, "failureMessage");

    }

}

控制器:


// App\Controllers\Web\PaymentController.php

function store(Request $request)

{

    $inputData = $this->validateRequest();

    $response = $this->paymentService->store($inputData);

    

    return back()->with($response->getExtraData(), $response->getMessage()) 

}



// App\Controllers\Api\PaymentController.php

function store(Request $request)

{

    // validation might be different because

    // api might need to authenticate with jwt etc.

    $inputData = $this->validateRequest();

    $response = $this->paymentService->store($inputData);


    return response()->json(['message' => $response->getMessage()], $response->getCode());

}

这将产生一个更干净的控制器,因为控制器将只处理请求验证和响应,同时将业务流程委托给服务类(支付服务)。业务逻辑也集中在服务层,这意味着如果业务发生变化,它将应用到API控制器和Web控制器。因此,它将把你从重构噩梦中拯救出来。


您可以探索不同的架构,例如 Clean Architecture + DDD。它将使您的开发体验更好,通过依赖抽象实现领域逻辑的集中化和层与层之间的低耦合。


查看完整回答
反对 回复 2023-07-08
  • 2 回答
  • 0 关注
  • 94 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信