You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 02:20:41