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

使用 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客户端发送的?我错过了设计模式吗?


Qyouu
浏览 123回答 2
2回答

慕森卡

最简单的方法是检查您应该发回什么样的响应:   //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);        }    }当然,您也可以将控制器逻辑提取到单独的库中,然后拥有两个单独的控制器方法,并且如果需要,仍然可以使用负责的对象。这实际上取决于您的用例以及最适合您的方法

一只名叫tom的猫

我认为另一种方法是利用服务存储库模式。您将应用程序服务包装在一个单独的类中。服务是控制器和存储库之间的交互器。流程看起来像[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.phpfunction store(Request $request){    $inputData = $this->validateRequest();    $response = $this->paymentService->store($inputData);        return back()->with($response->getExtraData(), $response->getMessage()) }// App\Controllers\Api\PaymentController.phpfunction 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。它将使您的开发体验更好,通过依赖抽象实现领域逻辑的集中化和层与层之间的低耦合。
打开App,查看更多内容
随时随地看视频慕课网APP