假设您的任务是从一所学校的在线申请系统导入数据。当学生提交申请时,数据存储在 Excel 文件中,需要将其导入到您的 Laravel 应用程序中。在本文中,我们将引导您完成使用 Filament 和 Laravel 有效处理大型 Excel 文件的过程。
Excel 导入包
对于此项目,我们将使用 Spatie\SimpleExcel 包从 Excel 文件中读取数据,并在后端进行所需的更改。此包还处理 CSV 文件。确保使用命令安装软件包: composer require spatie/simple-excel 。该软件包为复杂任务提供了许多有用的功能,但在本文中我们将重点介绍一个更简单的示例。
要开始数据处理任务,我们将在 Filament Application Resource 页面上创建一个操作按钮。此按钮 Student Applications Import 将处理导入过程。为简单起见,我们从 Resource 页面中删除了其余代码,如表单和表格。我们已通过 headerActions 将按钮放在表头中。
<?php
use App\Jobs\ApplicationsImportsJob;
class ApplicationResource extends Resource
{
protected static ?string $model = Application::class;
public static function form(Form $form): Form
{}
public static function table(Table $table): Table
{
return $table
->columns([])
->filters([])
->actions([])
->headerActions([
Tables\Actions\Action::make('Import Applications')
->form([
FileUpload::make('xlsxFile')
->label('XLSX File')
->disk('local')
->required()
->directory('imports'),
])->action(function (array $data) {
if ($data['xlsxFile'] !== null) {
$filePath = $data['xlsxFile'];
ApplicationsImportsJob::dispatch($filePath);
}
})
]);
}
}
以块的形式处理数据
接下来,我们需要创建一个作业来处理导入的数据。在我们的示例中,此作业名为 ApplicationsImportsJob。该作业将读取 Excel 文件,将数据分块为可管理的部分,并为每个块分派一个新作业。我们已将 chunk 每个 chunk 设置为 500 行,这在我们的项目中运行良好,但请随意尝试。
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Spatie\SimpleExcel\SimpleExcelReader;
class ApplicationsImportsJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(public $filename)
{
//
}
public function handle(): void
{
SimpleExcelReader::create(storage_path('app/' . $this->filename))
->getRows()
->chunk(500)
->each(fn ($chunk) => ApplicationsImportChunkJob::dispatch($chunk, $this->filename));
}
}
处理数据并保存
鉴于 Excel 文件中的数据量很大,因此将数据分解为可管理的块以进行高效处理非常重要。此作业将遍历 chunk 中的 500 行,并为每个学生创建一个新应用程序。它将保存 Excel 文件头中相应列名找到的姓名、电话和地址。在将作业标记为失败之前,将尝试该作业 5 次。
<?php
namespace App\Jobs;
use App\Models\Application;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ApplicationsImportChunkJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $tries = 5;
/**
* Create a new job instance.
*/
public function __construct(public $chunk, public $file)
{
//
}
/**
* Execute the job.
*/
public function handle(): void
{
foreach ($this->chunk as $row) {
Application::updateOrInsert([
'name' => $row['name'],
'phone' => $row['phone'],
'address' => $row['address'],
]);
}
}
}
设置用于处理大型 Excel 文件的 Laravel 作业后,下一步是运行这些作业以开始数据处理。运行作业涉及执行分派作业的代码,并允许 Laravel 在后台处理它们,而不会减慢主应用程序的速度。
在 Laravel 中,队列用于异步处理耗时的任务。当任务被分派时,它被添加到队列中,等待队列工作线程处理。如果您想了解如何在本地设置队列,请阅读文章 Laravel 11 for Beginners: Using Queues。要处理队列中的作业,您需要运行队列工作程序: php artisan queue:work 。
必须正确配置队列以确保您的作业能够运行。在项目的 .env 部分中,将 QUEUE_CONNECTION 设置为 redis,以利用其快速的内存数据存储功能。为了清楚起见,这里有一个片段:
QUEUE_CONNECTION=redis
REDIS_DATABASE=0
如果您在同一服务器上运行多个站点,请将每个站点分配给不同的 Redis 数据库,以防止任何重叠。只需相应地增加 REDIS_DATABASE 数字(例如,0、1、2 等)。
通过执行这些步骤并使用 Laravel 和 Spatie\SimpleExcel 包,您可以在 Filament 应用程序上高效处理大型 Excel 文件。将数据分解为可管理的块并使用专用作业处理它们,可确保导入过程顺利有效。