Laravel导出Blade视图到Excel时DOM加载失败的解决办法
Laravel Excel导出含多层循环Blade视图报错解决方案
问题说明
使用Laravel Excel导出包含多层循环的Blade视图时触发报错:
Failed to load D:\web\cottonello\storage\framework\cache\laravel-excel\laravel-excel-LDIPCoWBtHuyLG2C6xzWafwFdr0Pi4yI.html as a DOM Document
已验证简单表格、单循环视图可正常导出,执行过php artisan cache:clear,推测是多层循环导致HTML结构异常引发DOM解析失败。
相关代码
导出Excel控制器
public function view(): View { return view('dashboard.stock.table',[ 'products' => Product::all(), 'size' => Size::all(), 'color' => Color::all(), 'outlet' => Outlet::all(), ]); }
待导出的Blade视图表格
<table class="table"> <thead> <tr> <th>No</th> <th>Product</th> <th>Color</th> <th>Size</th> <th>Location</th> <th>Stock</th> </tr> </thead> <tbody> @foreach ($products as $product) <tr> <td rowspan={{ $color->count() * $size->count() }}>{{ $loop->iteration }}</td> <td rowspan={{ $color->count() * $size->count() }}>{{ $product->name }}</td> <td rowspan={{ $size->count() }}>{{ $color[0]->name }}</td> <td>{{ $size[0]->size }}</td> <td rowspan={{ $color->count() * $size->count() }}>Location : TSM, Nuris, Samasta, Ubud</td> <td>-Input Stok-</td> @foreach ($size->skip(1) as $item) <tr> <td>{{ $item->size }}</td> <td>-Input Stok-</td> </tr> @endforeach @foreach ($color->skip(1) as $item) <tr> <td rowspan={{ $size->count() }}>{{ $item->name }}</td> <td>{{ $size[0]->size }}</td> <td>-Input Stok-</td> @foreach ($size->skip(1) as $item) <tr> <td>{{ $item->size }}</td> <td>-Input Stok-</td> </tr> @endforeach </tr> @endforeach </tr> @endforeach </tbody> </table>
路由
Route::get('/dashboard/stock/table', [templateImport::class, 'view']);
库存控制器导出方法
public function template_export(){ return FacadesExcel::download(new templateImport, 'template.xlsx'); }
解决方案
1. 修复HTML表格结构合法性
Laravel Excel依赖DOMDocument解析HTML,原视图存在<tr>嵌套<tr>、行内列数与表头不匹配的问题,直接导致解析失败。修改后的视图代码:
<table class="table"> <thead> <tr> <th>No</th> <th>Product</th> <th>Color</th> <th>Size</th> <th>Location</th> <th>Stock</th> </tr> </thead> <tbody> @foreach ($products as $product) @foreach ($color as $colorItem) @foreach ($size as $sizeItem) <tr> <td @if($loop->parent->first && $loop->first) rowspan="{{ $color->count() * $size->count() }}" @endif> {{ $loop->parent->parent->iteration }} </td> <td @if($loop->parent->first && $loop->first) rowspan="{{ $color->count() * $size->count() }}" @endif> {{ $product->name }} </td> <td @if($loop->first) rowspan="{{ $size->count() }}" @endif> {{ $colorItem->name }} </td> <td>{{ $sizeItem->size }}</td> <td @if($loop->parent->first && $loop->first) rowspan="{{ $color->count() * $size->count() }}" @endif> Location : TSM, Nuris, Samasta, Ubud </td> <td>-Input Stok-</td> </tr> @endforeach @endforeach @endforeach </tbody> </table>
2. 优化数据传递(可选)
提前在控制器中处理数据为扁平化结构,降低视图循环复杂度:
public function view(): View { $products = Product::all(); $sizes = Size::all(); $colors = Color::all(); $templateData = []; foreach ($products as $product) { foreach ($colors as $color) { foreach ($sizes as $size) { $templateData[] = [ 'product' => $product, 'color' => $color, 'size' => $size, ]; } } } return view('dashboard.stock.table', compact('templateData', 'products', 'sizes', 'colors')); }
简化后的视图:
<table class="table"> <thead> <tr> <th>No</th> <th>Product</th> <th>Color</th> <th>Size</th> <th>Location</th> <th>Stock</th> </tr> </thead> <tbody> @foreach ($templateData as $index => $item) <tr> <td @if($index % ($colors->count() * $sizes->count()) == 0) rowspan="{{ $colors->count() * $sizes->count() }}" @endif> {{ floor($index / ($colors->count() * $sizes->count())) + 1 }} </td> <td @if($index % ($colors->count() * $sizes->count()) == 0) rowspan="{{ $colors->count() * $sizes->count() }}" @endif> {{ $item['product']->name }} </td> <td @if($index % $sizes->count() == 0) rowspan="{{ $sizes->count() }}" @endif> {{ $item['color']->name }} </td> <td>{{ $item['size']->size }}</td> <td @if($index % ($colors->count() * $sizes->count()) == 0) rowspan="{{ $colors->count() * $sizes->count() }}" @endif> Location : TSM, Nuris, Samasta, Ubud </td> <td>-Input Stok-</td> </tr> @endforeach </tbody> </table>
3. 清理缓存并重新测试
执行命令清空所有缓存,确保视图编译和Laravel Excel缓存生效:
php artisan cache:clear php artisan view:clear php artisan config:clear
内容的提问来源于stack exchange,提问作者eka dita
相关产品推荐
相关产品推荐

