如何无需自定义类修改Laravel Http客户端PendingRequest的请求负载?
解决Laravel Http客户端请求负载转XML的问题
你的思路方向是对的——利用PendingRequest的宏和beforeSending钩子来处理数据转换,但问题出在你修改的是$options的副本,而非实际要发送的请求内容。Laravel的beforeSending回调中,$options是按值传递的,所以你在回调里修改它不会影响原请求。不过不用自定义PendingRequest子类,我们可以直接操作Request实例来修改负载。
修正后的实现代码
这里是调整后的宏定义,能正确将数组负载转换为XML字符串:
use Illuminate\Http\Client\PendingRequest; use Illuminate\Http\Client\Request; // 假设你用的是Spatie的ArrayToXml,根据实际情况调整引入类 use Spatie\ArrayToXml\ArrayToXml; public function registerRequestMacros(): void { $rootElement = 'request'; PendingRequest::macro('acceptXml', function () { return $this->accept('application/xml'); }); PendingRequest::macro('convertDataToXml', function () use ($rootElement) { $this->beforeSending(function (Request $request) use ($rootElement) { $body = $request->body(); // 仅当body是数组时才转换为XML if (is_array($body) && !empty($body)) { // 转换数组为XML字符串 $xmlContent = ArrayToXml::convert($body, $rootElement); // 直接修改请求的body内容 $request->setBody($xmlContent); // 确保Content-Type头与内容匹配 $request->headers->set('Content-Type', 'application/xml'); } }); }); PendingRequest::macro('asXml', function () { $this->convertDataToXml(); // 使用raw格式,让客户端直接发送XML字符串 return $this->bodyFormat('raw')->acceptXml(); }); }
关键修改点说明
直接操作Request实例:
放弃修改$options,转而通过$request->body()获取当前请求的负载,转换后用$request->setBody()覆盖原内容,这样修改会直接作用于即将发送的请求。调整bodyFormat为raw:
调用asXml()时设置bodyFormat('raw'),是因为我们最终要发送的是XML字符串,而非Laravel默认的表单或JSON格式。这个设置告诉Http客户端直接将字符串作为请求体发送,不需要额外编码。确保请求头一致性:
在转换后显式设置Content-Type为application/xml,避免头信息和实际内容不匹配导致的接口解析错误。
使用示例
现在你可以像这样发送XML格式的请求:
$response = Http::asXml()->post('https://your-api-endpoint.com', [ 'user' => [ 'name' => 'John Doe', 'email' => 'john@example.com' ] ]);
这个请求会自动将数组转换为以<request>为根节点的XML字符串,并带上正确的请求头。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

