class TestController extends Controller{public function index() {return json(['code' => 10000, 'message' => '', 'data' => 1]) }}
再简便点,便是把这个 json 输出封装到基类,或者 trait 中供给用者自己调用。我也是这么利用,但在利用过程中,我在想能不能更加大略点,由于有时候仅仅是想返回数据而已。可不可以像下面的示例这样
class TestController extends Controller{public function index() {return 1; }}
只须要业务方法调用返回就可以了,不须要每次都利用类似下面的代码
class TestController extends Controller{public function index() {// 基类方法return $this->json(1) }}
更优雅的相应办法
在研究 Laravel 的源码时,我创造了一个有趣的事宜 RequestHandled,这个事宜在要求处理完成后被触发。通过监听这个事宜,我们可以在数据相应阶段进行处理,从而实现更优雅的 JSON 数据相应办法。看下面这段代码,目前这段代码在 Laravel11 中的 Illuminate\Foundation\Http 类中

public function handle($request){$this->requestStartedAt = Carbon::now();try {$request->enableHttpMethodParameterOverride();$response = $this->sendRequestThroughRouter($request);} catch (Throwable $e) {$this->reportException($e);$response = $this->renderException($request, $e); }// 在这里可以对相应做些什么$this->app['events']->dispatch(new RequestHandled($request, $response) );return $response;}
首先创建一个 Listener,利用 php artisan make:listener RequestHandledListener ,创建完成之后,Laravel 框架会自动帮注册,不须要手动去注册。
下面只是大略的示例,由于只须要 Json 相应,以是这里过滤掉所有非 JsonRespons 相应
class RequestHandledListener{public function handle(RequestHandled $event): void{$response = $event->response;if ($response instanceof JsonResponse) {$exception = $response->exception;if ($response->getStatusCode() == SymfonyResponse::HTTP_OK && !$exception) {$response->setData($this->formatData($response->getData()));}}}// 拦截数据,然后格式化数据// 详细内容跟规则可以根据实际业务设置protected function formatData(mixed $data): array{$responseData = ['code' => 10000, // 业务成功 code'message' => 'success', // 成功信息];$responseData['data'] = $data;return $responseData;}}
回到掌握器的时候,再利用下面的代码进行输出
class TestController extends Controller{public function index(){return 1;}}
创造根本没有任何浸染。根本不是 Json 相应啊。想一想为啥? 为什么掌握要输出 Json Response 工具呢?上面的代码到浏览器只会输出个 1,便是一个普通的相应,而不是 Json Response。以是须要想相应始终设置为 Json Reponse 工具。来写一个中间件办理这个问题。利用 php artisan make:middleware JsonResponseMiddleware 创建中间件
namespace App\Http\Middleware;use Illuminate\Http\JsonResponse;use Illuminate\Http\Request;use Illuminate\Http\Response;use Symfony\Component\HttpFoundation\BinaryFileResponse;class JsonResponseMiddleware{public function handle(Request $request, \Closure $next){$response = $next($request);// responseif ($response instanceof Response) {return new JsonResponse($response->getContent());}return $response;}}
切换到路由 web.php 文件,加上路由
Route::get('/', [\App\Http\Controllers\IndexController::class, 'index'])->middleware(\App\Http\Middleware\JsonResponseMiddleware::class);
回到浏览器,刷新下,你将会看到下面的输出
{"code": 10000,"message": "success","data": "1"}
处理不同要求来源
有时,我们可能须要根据要求的来源不同来处理相应数据的格式。例如,后台管理系统和客户真个要求可能须要不同的数据格式。这时,我们可以通过设置要求头信息来区分不同的要求来源。下面只是一个示例。现在前端要求一样平常都用 axios, 以是只要在全局 axios 工具设置一个头信息。如下
axios.defaults.headers['Request-from'] = 'WhereFrom'
后端可以根据头信息来判断是否须要利用该返回,可以这么做,回到 RequestHandledListener 中
public function handle(RequestHandled $event): void{// 只有后台要求才处理if (Request::hasHeader('Request-from')&& Str::of(Request::header('Request-from'))->exactly('WhereFrom')) {$response = $event->response;if ($response instanceof JsonResponse) {$exception = $response->exception;if ($response->getStatusCode() == SymfonyResponse::HTTP_OK && !$exception) {$response->setData($this->formatData($response->getData())); } } }}
如何相应缺点码
不对啊,这里写去世的 success,那么失落败要求该怎么做?全体项目失落败都是用非常处理就行,以是只须要在全局非常这里处理下。首先确定下我们数据格式是这样的
{"code": 10000,"message": "success","data": "1"}
当到掌握器中 Index 方法抛出一个非常
public function index(){throw new \Exception('test');}
会输出这样的内容
{code: 10000,message: "success",data: '<!DOCTYPE html><html lang="en" class="auto"><!--' // 非常一大段的文本,html 输出}
这里有三个问题
Code 码没有利用非常的还是固定的message 信息不是非常抛出来的data 不须要有数据,可以不用返回为理解决这三个问题,可以这么做,首先我们创建一个基类 abstract class Exception, php artisan make:exception BaseException, 内容如下
use Symfony\Component\HttpKernel\Exception\HttpException;abstract class BaseException extends HttpException{protected $code = 0;public function __construct(string $message = '', int $code = 0) {parent::__construct($this->statusCode(), $message ?: $this->message, null, [], $code); }public function statusCode(): int {// 对付非常统一返回 500,须要变动可以通过子类修正对应的 codereturn 500; }public function render(): array {return ['code' => $this->code,'message' => $this->message, ]; }}
基类创建好之后呢,再来创建子类,由于业务中的缺点类型各种各样,以是非常子类也是很多的,但是记住都须要继续 BaseException,还是用上面的 artisan 创建一个失落败非常,代码如下
namespace App\Exceptions;use Exception;class FailException extends BaseException{//protected $code = 10001;protected $message = 'fail';}
再回到掌握中
public function index(){ throw new FailException();}
刷新浏览器之后,浏览器会输出精确的缺点返回了。很不错,办理了上面的三个问题
{"code": 10001,"message": "fail"}
总结
这个办法多多少少有点黑盒了。对付刚接手的人,如果不去翻代码或者有人来讲解的话,可能多多少有点懵的 。但是如果理解了,我认为将 response json 这样输出从业务代码中解构出来还是蛮好的。如果运用的相应数据险些不变动,个人更喜好这样的办法去返回,不然掌握器大量的 response()->json() 这样的代码看着挺烦人的。如有更好的方法,欢迎谈论。
[原文链接: 另辟路子!
如何在 Laravel 更优雅的相应 JSON 数据
](https://catchadmin.com/post/2024-03/laravel-unified-response)