如何正确扩展Laravel Http Facade添加自定义响应辅助方法
Laravel Http Client 扩展响应辅助方法实现方案
你不需要通过继承客户端类的方式扩展,Laravel的Http客户端相关类原生支持宏扩展,和你已经在用的Facade宏写法完全兼容,直接按以下方式实现即可:
核心原理
Http客户端涉及的两个核心类都支持macro宏扩展,互不冲突:
- 你平时调用的
Http门面对应的Illuminate\Http\Client\PendingRequest:用来封装请求公共逻辑(比如固定baseUrl、固定请求头、签名逻辑等),也就是你已经在使用的宏挂载类 - 请求返回的响应实例
Illuminate\Http\Client\Response:用来封装响应解析、业务判断逻辑,也就是你需要新增解析辅助方法的挂载类
快速实现步骤
1. 先复用原生能力减少重复代码
你现在重复编写的解析代码其实有原生替代方案,不需要手动处理流内容解码:
响应实例自带
json()方法,接收字段路径作为参数,直接返回解析后的值,支持点语法取多层嵌套字段,内部已经兼容了解码失败、内容为空等边界情况
你写的json_decode($this->getBody()->getContents())->id等价于原生调用$response->json('id')
2. 注册自定义响应宏
如果原生方法还不能满足你的复用需求(比如需要封装固定业务逻辑、常用字段快捷读取),直接在服务提供者的boot方法中给Response类注册宏即可,推荐放在App\Providers\AppServiceProvider,宏逻辑较多可以单独新建服务提供者存放。
示例代码:
<?php namespace App\Providers; use Illuminate\Http\Client\Response; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Http; class AppServiceProvider extends ServiceProvider { public function boot() { // 你之前已经在Http门面上注册的宏保持不变,不需要任何修改 Http::macro('apiClient', function () { return Http::withToken(config('custom.api_token')) ->baseUrl(config('custom.api_base')) ->timeout(10); }); // 新增响应类辅助宏 Response::macro('getResId', function () { // 宏内$this指向当前响应实例,可直接调用响应类所有原生方法 return $this->json('id'); }); // 示例:封装通用业务成功判断,自动抛出业务异常 Response::macro('throwBusinessError', function () { if ($this->json('code') !== 0) { throw new \RuntimeException($this->json('msg', '接口请求失败'), $this->json('code', -1)); } return $this; }); // 示例:快捷读取业务数据节点 Response::macro('getResData', function ($key = null, $default = null) { return $this->json($key ? "data.$key" : 'data', $default); }); } }
3. 调用方式
和你之前的写法完全一致,直接在请求后链式调用新增的辅助方法即可:
// 快捷取id $id = Http::apiClient()->post('/user/create', $params)->getResId(); // 自动判断业务状态+取数据 $userInfo = Http::apiClient()->get('/user/detail', ['id' => $id]) ->throwBusinessError() ->getResData();
注意事项
- 不要手动调用
getBody()->getContents()读取响应内容,响应流读取一次之后就会清空,后续再调用读取方法会返回空内容,用原生json()、body()方法会自动处理流缓存问题 - 宏方法支持链式调用,只要在宏末尾返回
$this就可以继续拼接其他方法 - 所有响应宏全局生效,不管你是通过自定义的Http宏发起请求,还是直接调用
Http::get()原生方法发起请求,返回的响应实例都可以调用你注册的辅助方法
内容的提问来源于stack exchange,提问作者Kristian Vasilev
相关产品推荐
相关产品推荐

