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

Laravel9+maatwebsite/excel:从MySQL生成指定格式Excel矩阵

问题描述

需要从数据库生成如下格式的Excel文件:

User NameUser LastnameGroup AGroup BGroup X
JohnDoeXX
JaneDoeX

现有三张表:User表、Group表及关联用户与组的Group Matching表(一个用户可属于多个组)。已通过查询组列表动态构建表头,并将"User Name"和"User Lastname"添加至表头数组:

public function headings(): array
{
    $header = array();
    $search ="Group";
    $groupList = new \App\Models\Group;
    $groupList = $groupList::where('name','LIKE',"%{$search}%")->get();;
    foreach($groupList as $key=>$value)  {
        $header[]=$value["name"];    
    }
    array_unshift($header,"User Name", "User Lastname");

    return $header;
}

注:输出的组数量不可控。接下来,已获取包含用户名、姓氏及组归属的记录集合:

public function array(): array
{
    $datas = array();
    $MyUsers = MyUser::with(['groupMatching'])->get();
    foreach($MyUsers as $MyUser) {
       
        $datas[$MyUser->id]["name"] = $MyUser->lastname;
        $datas[$MyUser->id]["firstname"] = $MyUser->firstname;
        foreach($MyUser->groupMatching as $MyMember) {
            $datas[$MyUser->id]["groups"][]  = $MyMember->Group_name;

        }

        
    }
    return $datas;
}

$datas结构如下:

array:23 [▼ // app/Exports/MyUsersExport.php:31
  4 => array:3 [▼
    "name" => "Doe"
    "firstname" => "John"
    "groups" => array:3 [▼
      0 => "Group A"
      1 => "Group X"
    ]
  5 => array:3 [▼
    "name" => "Jane"
    "firstname" => "Doe"
    "groups" => array:2 [▼
      0 => "Group X"
    ]
  ]
]

使用Laravel 9和maatwebsite/excel 3.1,如何实现目标输出,在匹配的列名/数据对应位置填充X?


解决方案

核心思路是让返回的每行数据与表头顺序完全对应,逐个判断用户是否属于对应组,填充X或空值。具体步骤如下:

1. 抽离表头逻辑(避免重复查询)

把生成表头的代码抽成私有方法,同时供headings()和array()调用,减少数据库查询次数:

private function getHeaders(): array
{
    $search = "Group";
    // 直接提取组名数组,比get()更高效
    $groupNames = \App\Models\Group::where('name', 'LIKE', "%{$search}%")->pluck('name')->toArray();
    array_unshift($groupNames, "User Name", "User Lastname");
    
    return $groupNames;
}

2. 重写headings()方法

复用抽离的表头逻辑:

public function headings(): array
{
    return $this->getHeaders();
}

3. 修改array()方法生成对应行数据

遍历每个用户,按照表头顺序生成每行数据,判断用户是否属于当前组并填充X:

public function array(): array
{
    $headers = $this->getHeaders();
    // 提取表头中除前两列外的所有组列
    $groupColumns = array_slice($headers, 2);
    
    $rows = [];
    $MyUsers = MyUser::with(['groupMatching'])->get();
    
    foreach ($MyUsers as $MyUser) {
        // 将用户所属组转为键数组,提升存在性判断效率
        $userGroups = collect($MyUser->groupMatching)->pluck('Group_name')->flip()->toArray();
        
        $row = [];
        // 填充前两列:User Name(名)、User Lastname(姓)
        $row[] = $MyUser->firstname;
        $row[] = $MyUser->lastname;
        
        // 遍历所有组列,填充X或空值
        foreach ($groupColumns as $groupName) {
            $row[] = isset($userGroups[$groupName]) ? 'X' : '';
        }
        
        $rows[] = $row;
    }
    
    return $rows;
}

代码说明

  • 使用pluck('name')直接获取组名数组,比get()后遍历更高效
  • flip()将用户所属组数组的键值互换,把组名作为键,判断用户是否属于该组时只需用isset(),性能更优
  • 严格按照表头顺序生成每行数据,保证Excel中列与数据完全对应
  • 最终返回的二维数组$rows完全符合maatwebsite/excel的要求,无需额外处理即可生成目标格式的Excel

内容的提问来源于stack exchange,提问作者STANISLAS PIERRE-ALEXANDRE

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 07:53:21