Laravel+Vue导出Excel遇问题:foreach循环报错或返回异常值
Laravel+Vue导出预订数据到Excel遍历报错排查
场景概述
基于Laravel后端、Vue前端的项目,需导出预订数据到Excel。前端通过带参数的href调用导出接口,使用JSON.stringify处理数据后URL编码正常,但在后端导出的Excel视图中遍历数据时,出现两种异常:要么返回1,要么提示错误foreach() argument must be of type array|object, null given。
相关代码片段
前端调用代码
<a class="btn btn-primary" target="_blank" :href="server + '/admin/booking-status-report/excel?method=export'+ '&data=' + JSON.stringify(this.bookings)">Print</a>
注:未使用
JSON.stringify时,URL中data参数会显示为[object%20Object],[object%20Object],使用后编码格式正常。
后端Controller代码
public function export(Request $request) { $dataParam = $request->query('data'); if (!empty($dataParam)) { $data = json_decode(urldecode($dataParam), true); return Excel::store(new BookingStatusExport($data), 'booking-status-report.xlsx'); } else { return response()->json(['error' => 'Data parameter is missing'], 400); } }
导出类BookingStatusExport代码
private $data; public function __construct($data) { $this->data = $data; } public function view(): View { return view('excel.booking-status-report', [ 'data' => $this->data ]); }
视图遍历代码
@foreach($data as $d) <tr> <td>{{ $d['trip_date'] }}</td> <td>{{ $d['trip_time'] }}</td> <td>{{ $d['invoice'] }}</td> <td>{{ $d['customer_name'] }}</td> </tr> @endforeach
排查与修复方案
1. 修正JSON解码逻辑
Laravel的$request->query()已经自动完成URL解码,手动调用urldecode()会导致二次解码,破坏原始JSON结构,导致json_decode返回null。修改Controller代码:
// 移除urldecode,直接解码 $data = json_decode($dataParam, true);
同时前端建议对JSON字符串额外做URL编码,避免特殊字符干扰:
:href="server + '/admin/booking-status-report/excel?method=export&data=' + encodeURIComponent(JSON.stringify(this.bookings))"
2. 确保导出类实现正确接口
使用Maatwebsite/Laravel-Excel时,导出类必须实现FromView接口,否则框架无法识别视图导出逻辑:
use Maatwebsite\Excel\Concerns\FromView; use Illuminate\Contracts\View\View; class BookingStatusExport implements FromView { private $data; public function __construct($data) { // 兜底空数组,避免null传入 $this->data = is_array($data) ? $data : []; } public function view(): View { return view('excel.booking-status-report', [ 'data' => $this->data ]); } }
3. 视图层增加数据校验
在视图中提前判断数据有效性,避免foreach直接遍历null:
@if(is_array($data) && count($data) > 0) @foreach($data as $d) <tr> <td>{{ $d['trip_date'] ?? '' }}</td> <td>{{ $d['trip_time'] ?? '' }}</td> <td>{{ $d['invoice'] ?? '' }}</td> <td>{{ $d['customer_name'] ?? '' }}</td> </tr> @endforeach @else <tr> <td colspan="4">暂无数据</td> </tr> @endif
4. 规避GET请求长度限制
如果预订数据量较大,GET请求的URL长度限制会导致JSON字符串被截断,解码后为null。建议改用POST请求传递数据:
- 前端用axios发送POST请求:
exportExcel() { axios.post('/admin/booking-status-report/excel', { data: this.bookings }, { responseType: 'blob' }).then(res => { const url = window.URL.createObjectURL(new Blob([res.data])) const a = document.createElement('a') a.href = url a.download = 'booking-status-report.xlsx' document.body.appendChild(a) a.click() window.URL.revokeObjectURL(url) document.body.removeChild(a) }) } - 后端修改接收逻辑:
public function export(Request $request) { $data = $request->input('data'); if (!empty($data)) { return Excel::download(new BookingStatusExport($data), 'booking-status-report.xlsx'); } else { return response()->json(['error' => 'Data parameter is missing'], 400); } }
内容的提问来源于stack exchange,提问作者Coder
相关产品推荐
相关产品推荐

