Skip to content

数据导出功能

数据导出功能是后台管理系统的核心需求,CatchAdmin 专业版提供了完整的 Excel 数据导出解决方案。基于 Laravel Excel 进行深度封装,支持简单的数据导出和高性能的大数据量导出。同时集成 xlswriter 扩展,可实现百万级数据导出且内存占用极低

基本使用

CatchAdmin 专业版提供了抽象基础类,继承该类可快速实现 Excel 数据导出功能。以下是用户数据导出的实现示例

php
namespace Modules\User\Export;

// 该类就是基础核心类,通过集成它可以快速实现导出
use Catch\Support\Excel\Export;

class User extends Export
{
    // 这里需要设置导出的头信息
    protected array $header = [
        'id', '昵称', '邮箱', '创建时间'
    ];

    // 实现 array 方法,返回导出的数据
    public function array(): array
    {
        // TODO: Implement array() method.
        return \Modules\User\Models\User::query()
            ->select('id', 'username', 'email', 'created_at')
            ->without('roles')
            ->get([
                'id', 'username', 'email', 'created_at'
            ])->toArray();
    }
}

只需要轻松的几行代码,便可实现导出 Excel。这只是实现了导出类,那么如何使用呢? 也很简单,例如在 UserController 添加 export 方法,注入导出类

php
public function export(\Modules\User\Export\User $export)
{
    return $export->download();
}

直接通过 download 方法实现 excel 的下载。这个看起来似乎还比较繁琐,每次都要写一个导出类。一般平时导出的需求没有这么复杂,那么有没有更加简便的方法?答案是有的。看下面的例子

php
public function export()
{
    return User::query()
        ->select('id', 'username', 'email', 'created_at')
        ->without('roles')
        ->get()
        ->download(['id', '昵称', '邮箱', '创建时间']);
}

CatchAdmin 专业版通过扩展 Laravel Collection 添加 download 方法,无需编写专门的导出类即可快速实现 Excel 数据导出功能。

对于大数据量导出场景,同步导出可能导致请求超时或内存溢出。当需要导出数万条数据且包含复杂计算查询时,虽然可以使用 Laravel Queue,但缺乏任务状态监控和集中管理功能。CatchAdmin 专业版提供了异步任务管理机制,支持导出任务的状态追踪和进度监控

php
<?php
namespace Modules\User\Export;

// 首先这里需要继承 AsyncTaskInterface 接口
use Catch\Contracts\AsyncTaskInterface;
use Catch\Support\Excel\Export;

// 然后引入 AsyncTaskInterface
use Modules\System\Support\Traits\AsyncTaskDispatch;

class User extends Export implements AsyncTaskInterface
{
    // 这里 use 它,这样任务就可以变成异步的了
    use AsyncTaskDispatch;

    protected array $header = [
        'id', '昵称', '邮箱', '创建时间'
    ];

    public function array(): array
    {
        // TODO: Implement array() method.
        return \Modules\User\Models\User::query()
            ->select('id', 'username', 'email', 'created_at')
            ->without('roles')
            ->get([
                'id', 'username', 'email', 'created_at'
            ])->toArray();
    }
}

好了,任务搞好了,再来看看控制器如何写

php
/**
 * @return void
 */
public function export(\Modules\User\Export\User $export)
{
    // 控制器就更加简单了,直接 push 推送即可
    return $export->push();
}

完成异步任务配置后,需要启动任务调度程序。在 app/Console/Kernel.php 中添加定时任务调度

php
protected function schedule(Schedule $schedule): void
{
    $schedule->command('async:task')->everyMinute();
}

异步任务的执行状态、进度信息和详细日志,可在后台管理系统的系统管理/异步任务模块中实时查看和管理

大数据量导出

Xlswriter

Xlswriter 是高性能的 Excel PHP 扩展,专为大数据量处理优化。

CatchAdmin 专业版对 xlswriter 进行了深度封装,支持百万级数据导出且内存占用极低。通过优化的数据处理机制,可实现大规模数据导出而不会导致内存溢出。由于大数据量导出耗时较长,建议配合异步任务使用

INFO

只支持游标(cursor)查询模式,也就是惰性查询。非惰性会退化成 Laravel Excel 实现

快捷导出

php
// 使用 Xlswriter 进行高性能数据导出
User::query()
    ->select('id', 'username', 'email', 'created_at')
    ->cursor() // 使用游标查询,避免内存溢出
    ->download(['id', '昵称', '邮箱', '创建时间']);

支持游标模式分块导出,进一步优化内存使用

php
// 结合游标查询和分块处理,提升性能
User::query()
    ->select('id', 'username', 'email', 'created_at')
    ->cursor() // 游标查询模式
    ->chunk(5) // 分块处理,每次处理 5 条记录
    ->download(['id', '昵称', '邮箱', '创建时间']);

单独导出类

也可以写一份单独导出类,可支持异步

php
<?php

namespace Modules\User\Export;

use Catch\Contracts\AsyncTaskInterface;
use Illuminate\Support\LazyCollection;
use Modules\System\Support\Traits\AsyncTaskDispatch;
use Catch\Support\Excel\XlsWriterExport;

class UserXlsWriter extends XlsWriterExport implements AsyncTaskInterface
{
    use AsyncTaskDispatch;

    protected array $header = [
        'id', '昵称', '邮箱', '创建时间',
    ];

    /**
     * 支持全部导出,也支持惰性导出,大数据量一定要用惰性导出
     */
    public function array(): array|LazyCollection
    {
        // TODO: Implement array() method.
        return User::query()
            ->select('id', 'username', 'email', 'created_at')
            ->limit(100)
            ->cursor()
            ->chunk(10);
    }

    /**
     * 设置样式
     */
    public function formats(): array
    {
        $handle = $this->excelObject->getHandle();

        $format    = new \Vtiful\Kernel\Format($handle);
        $boldStyle = $format->bold()->fontSize(10)->toResource();

        return [
            ['A1', 10, $boldStyle]
        ];
    }

    /**
     * 编辑密码保护,注意不是文档密码保护
     *
     * @return string|null
     */
    public function password():?string
    {
        return '123456';
    }
}

CSV 方案

对于超大规模数据导出,推荐使用 CSV 格式。虽然异步任务支持大批量数据导出,但 Excel 格式在极大数据量下仍可能出现内存不足问题。CatchAdmin 专业版的 CSV 导出方案经过优化,支持百万级数据导出且内存占用极低。在测试环境中成功导出 130 万条数据,内存消耗控制在合理范围内

php
// CSV 大数据量导出示例
return User::query()
            ->select('id', 'username', 'email', 'created_at')
            ->without('roles')
            // 必须使用游标查询以确保低内存占用
            ->cursor()
            ->downloadAsCsv(['id', '昵称', '邮箱', '创建时间']);

WARNING

记住一定要使用 cursor 游标查询数据,否则会导出失败