akki / bulkexportcsv
将无限记录导出为CSV
Requires
- php: ^7.3|^8.0
- anourvalar/eloquent-serialize: ^1.2
README
简介
此包将帮助您使用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未成功准备。为了处理每个事件,包发布事件及其相应的监听器
- BulkExportCSVStarted: 当CSV开始准备时,此事件被触发
- BulkExportCSVJobCompleted: 当特定作业完成时,为每个队列作业触发此事件。
- BulkExportCSVSucceeded: 当CSV成功准备时,即队列分批成功完成时,触发此事件。
- 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
方法类似的Columns
和Data
参数。download
方法即时创建CSV,即不将CSV写入服务器磁盘,并将可下载的CSV文件返回到浏览器。在前端,要强制浏览器直接下载CSV,需要让浏览器调用API,可以使用location.href
来实现。如果更喜欢使用AJAX调用API,则响应中的download
方法将提供CSV的内容,因此在前端可以使用blob创建CSV。
如果只使用download
方法,则不需要任何配置。可以根据自己的喜好使用build
和download
方法,如果导出的数据很大(可以使用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:table
和queue:batches-table
,迁移表
php artisan migrate
现在可以遵循上面提到的Laravel中的相同用法。
学习资源
YouTube上有一系列视频,可以了解如何使用此软件包,点击此处。
贡献
您可以通过发现错误和打开问题来为此软件包做出贡献。请务必在您创建的拉取请求或问题中添加软件包的版本。例如,[1.0.0]在build
方法上发生致命错误)