akki/bulkexportcsv

将无限记录导出为CSV

v3.0.0 2023-05-20 11:49 UTC

This package is auto-updated.

Last update: 2024-09-20 14:40:29 UTC


README

Latest Stable Version License

简介

此包将帮助您使用laravel的eloquent查询和json资源导出无限数据。它基于laravel的队列分批。它支持所有eloquent支持的数据库。

安装

安装 BulkExportCSV

composer require akki/bulkexportcsv

发布配置文件 config/bulkexportcsv.php,模型 App\Models\BulkExportCSV.php,迁移 bulk_export_csv 表,事件和监听器

php artisan vendor:publish --provider="Akki\BulkExportCSV\ServiceProvider"

准备队列表的迁移

php artisan queue:table
php artisan queue:batches-table

迁移表

php artisan migrate

使用方法

构建查询

准备一个eloquent查询,确保查询没有get(),first(),skip(),limit()方法。默认情况下,包将导出查询给出的所有记录。

$query = \App\Models\User::query();
$query->with('serviceProvider')->where('country', 'IN');

创建JSON资源

php artisan make:resource UserResource

UserResource.php

public function toArray($request)
{
    return [
        'name' => $this->name,
        'email' => $this->email,
        'service_provider' => $this->serviceProvider->org_name,
        'contact_number' => $this->contact_number,
    ];
}

导出为CSV

build 方法将启动导出CSV过程。

$query = \App\Models\User::query();
$query->with('serviceProvider')->where('country', 'IN');

$resource_namespace = 'App\Http\Resources\UserResource';

$bulkExportCSV = \BulkExportCSV::build($query, $resource_namespace);

build 方法返回指向已发布的 bulk_export_csv 表的 BulkExportCSV 模型,它提供了有关CSV请求的所有信息。如果要导出的数据较少,可以使用下载方法。
但是,在通过build方法导出CSV之前,请确保正确填写以下内容。

配置

编辑 config/bulkexportcsv.php 以满足您的需求。

/** @file config/bulkexportcsv.php */

return [
    /*
    * Number of Records to be fetched per job
    */
    'records_per_job' => 10000,

    /*
    * records will be fetched in chunks for better performance
    */
    'chunks_of_records_per_job' => 2,

    /*
    * Directory where CSV will be prepared inside storage folder   
    */
    'dir' => 'app/public/exportCSV',

    /*
    * Database connection for bulk_export_csv table  
    */
    'db_connection' => env('DB_CONNECTION', 'mysql'),

    /*
    * Queue connection for jobs  
    */
    'queue_connection' => env('QUEUE_CONNECTION', 'database'),

    /*
    * Name of queue where job will be dispatched  
    */
    'queue' => 'default',

    /*
    * Name of queue job batch   
    */
    'batch_name' => 'Bulk Export CSV',

    /*
    * The number of seconds the job can run before timing out
    * null takes default value
    * The pcntl PHP extension must be installed in order to specify job timeouts   
    */
    'job_timeout' => null,

    /*
    * if any job fails, it stops CSV preparation process
    * Decide whether partial CSV prepared should get deleted or not   
    */
    'delete_csv_if_job_failed' => false
];

事件

当CSV开始通过队列作业准备时,这些是典型的事件:CSV开始准备 => 队列作业完成 => 队列分批完成且CSV已成功准备或由于异常而停止队列分批,因此CSV未成功准备。为了处理每个事件,包发布事件及其相应的监听器

  1. BulkExportCSVStarted: 当CSV开始准备时,此事件被触发
  2. BulkExportCSVJobCompleted: 当特定作业完成时,为每个队列作业触发此事件。
  3. BulkExportCSVSucceeded: 当CSV成功准备时,即队列分批成功完成时,触发此事件。
  4. BulkExportCSVFailed: 当任何特定队列作业抛出异常并因此停止队列分批过程时,触发此事件,因此CSV未成功准备。
    这些事件都接受BulkExportCSV模型作为参数。您可以将这些事件广播出去,我们建议使用ShouldBroadcastNow接口,以便事件与队列作业同步广播。

bulk_export_csv表

当CSV开始准备时,您可以使用已发布的"bulk_export_csv"表来访问其当前状态,该表具有以下列。 BulkExportCSV模型指向此表

[
    'jobs_id' => unique ID generated for an export CSV request
    'csv_name' => CSV file name
    'total_records' => total number of records exported
    'total_jobs' => total jobs required to export CSV
    'completed_jobs' => when export CSV starts, this column gets updated with number of completed jobs
    'progress' => the completion percentage of the CSV export
    'export_status' => export status of CSV as 'InProgress', 'Completed', 'Error' or 'Cancelled'
    'each_jobs_time' => time taken by each job processed
    'average_jobs_time' => average time all jobs taken
    'error' => Exception error if any job fails or 'BulkExportCSVSucceeded' or 'BulkExportCSVFailed' events threw exception
    'config' => bulk export configuration used for an export CSV request
    'user_id' => ID of auth user requesting export CSV
    'batch_id' => batch_id of job batching process
]

队列配置

确保您已正确填写config/queue.php。安装Supervisor,在其配置文件中,必须提及用于bulkExportCSV的队列名称。例如,在config/bulkexportcsv.php中,如果queue名称为bulkExportCSV,则命令必须是

php artisan queue:work --queue=bulkExportCSV,default

当然,根据您的需求,您可以指定队列工作进程应按优先级处理哪些队列。如果您使用ShouldBroadcast接口广播事件,请确保将其队列名称也添加到此处。

在'BulkExportCSV'的'build'方法中的更多选项

定义导出CSV的列

默认情况下,包从json资源本身获取列名。但可以定义所需的自定义列

$columns = ['Name', 'Email', 'Service Provider', 'Contact Number'];
$bulkExportCSV = \BulkExportCSV::build($query, $resource_namespace, $columns);

在资源中访问请求数据

在许多情况下,我们需要在JSON资源中获取经过身份验证的用户数据或请求数据。由于导出CSV是在后台发生的,因此无法访问请求,但可以通过使用config('bulkexportcsv.data')将数据发送到JSON资源或优雅的模型访问器或事件监听器。

$user = auth()->user();
$data = ['user' => $user, 'request' => $request->all(), 'csv_info' => 'Toal Users on Platform'];
$columns = []; //if columns are defined as empty, then columns will be taken from json resource itself
$bulkExportCSV = \BulkExportCSV::build($query, $resource_namespace, $columns, $data);

JSON资源

public function toArray($request)
{
    $data = config('bulkexportcsv.data');
    $user = $data['user'];
    $request = $data['request'];

    return [
        'name' => $this->name,
        'email' => $this->email,
        'service_provider' => $this->when($user->role == 'admin', $this->serviceProvider->org_name??"-"),
        'contact_number' => $request['contact_number'],
    ];
}

数据数组中的csv_info键在BulkExportCSV模型中特别可访问,作为$bulkExportModal->config->csv_info

如果对JSON资源进行了更改,请务必重新启动队列工作进程。

额外方法

该软件包使用Akki\BulkExportCSV\Models\BulkExportCSVModel模型来访问“bulk_export_csv”表。此模型扩展自已发布的App\Models\BulkExportCSV模型。

findByJobsId

要使用jobs_id从“bulk_export_csv”表获取记录,可以使用findByJobsId方法

use Akki\BulkExportCSV\Models\BulkExportCSVModel;

$bulkExportCSVInfo = BulkExportCSVModel::findByJobsId($jobs_id);

cancelExportCSVProcess

要取消正在进行的导出CSV过程,可以使用cancelExportCSVProcess方法

use Akki\BulkExportCSV\Models\BulkExportCSVModel;

BulkExportCSVModel::cancelExportCSVProcess($jobs_id);

下载CSV

如果想要直接下载CSV而不是通过队列作业过程,则使用download方法

return \BulkExportCSV::download($query, $resource_namespace);

在此,还可以传递与build方法类似的ColumnsData参数。download方法即时创建CSV,即不将CSV写入服务器磁盘,并将可下载的CSV文件返回到浏览器。在前端,要强制浏览器直接下载CSV,需要让浏览器调用API,可以使用location.href来实现。如果更喜欢使用AJAX调用API,则响应中的download方法将提供CSV的内容,因此在前端可以使用blob创建CSV。

如果只使用download方法,则不需要任何配置。可以根据自己的喜好使用builddownload方法,如果导出的数据很大(可以使用eloquent上的count()方法知道),则最好使用build方法;否则,download方法也是一个合适的选择。

LUMEN中的安装

安装 BulkExportCSV

composer require akki/bulkexportcsv

服务提供程序应手动在bootstrap/app.php中注册,并启用一些额外的必需选项

// regiser service provider
$app->register(Akki\BulkExportCSV\ServiceProvider::class);
// Enable Facades
$app->withFacades();
// Enable Eloquent
$app->withEloquent();
// Enable bulk export configuration
$app->configure('bulkexportcsv');
// BulkExportCSV class alias
if (!class_exists('BulkExportCSV')) {
    class_alias('Akki\\BulkExportCSV\\Facades\\BulkExport', 'BulkExportCSV');
}
// EloquentSerialize class alias
if (!class_exists('EloquentSerialize')) {
    class_alias('AnourValar\EloquentSerialize\Facades\EloquentSerializeFacade', 'EloquentSerialize');
}

如果遇到错误'ReflectionException' with message 'Class path.storage does not exist',请将存储文件夹路径在bootstrap/app.php中声明在$app定义之后

$app = new Laravel\Lumen\Application(
    dirname(__DIR__)
);
// declare path to storage folder
$app->instance('path.storage', app()->basePath() . DIRECTORY_SEPARATOR . 'storage');

如果遇到错误Target [Illuminate\Contracts\Routing\ResponseFactory] is not instantiable,请在AppServiceProvider.php中添加以下内容

public function register()
{
    $this->app->singleton(\Illuminate\Contracts\Routing\ResponseFactory::class, function() {
        return new \Laravel\Lumen\Http\ResponseFactory();
    });
}

复制所需的文件

mkdir -p config
cp vendor/akki/bulkexportcsv/src/config/bulkexportcsv.php config/bulkexportcsv.php
cp vendor/akki/bulkexportcsv/src/Models/BulkExportCSV.txt app/Models/BulkExportCSV.php
cp vendor/akki/bulkexportcsv/src/database/migrations/create_bulk_export_csv_table.txt database/migrations/2023_01_01_000000_create_bulk_export_csv_table.php
cp vendor/akki/bulkexportcsv/src/Events/BulkExportCSVStarted.txt app/Events/BulkExportCSVStarted.php
cp vendor/akki/bulkexportcsv/src/Events/BulkExportCSVJobCompleted.txt app/Events/BulkExportCSVJobCompleted.php
cp vendor/akki/bulkexportcsv/src/Events/BulkExportCSVSucceeded.txt app/Events/BulkExportCSVSucceeded.php
cp vendor/akki/bulkexportcsv/src/Events/BulkExportCSVFailed.txt app/Events/BulkExportCSVFailed.php
cp vendor/akki/bulkexportcsv/src/Listeners/ListenBulkExportCSVStarted.txt app/Listeners/ListenBulkExportCSVStarted.php
cp vendor/akki/bulkexportcsv/src/Listeners/ListenBulkExportCSVJobCompleted.txt app/Listeners/ListenBulkExportCSVJobCompleted.php
cp vendor/akki/bulkexportcsv/src/Listeners/ListenBulkExportCSVSucceeded.txt app/Listeners/ListenBulkExportCSVSucceeded.php
cp vendor/akki/bulkexportcsv/src/Listeners/ListenBulkExportCSVFailed.txt app/Listeners/ListenBulkExportCSVFailed.php

从Laravel本身复制queue:tablequeue:batches-table,迁移表

php artisan migrate

现在可以遵循上面提到的Laravel中的相同用法

学习资源

YouTube上有一系列视频,可以了解如何使用此软件包,点击此处

贡献

您可以通过发现错误和打开问题来为此软件包做出贡献。请务必在您创建的拉取请求或问题中添加软件包的版本。例如,[1.0.0]在build方法上发生致命错误)