本文目录导读:

在 Laravel 中处理外部数据导入,通常需要解决数据获取、数据清洗、批量存储和错误处理这几个核心问题,以下是几种常见的处理方案和最佳实践。
数据获取方式
从文件导入(CSV/Excel)
use Illuminate\Support\Facades\Storage;
use League\Csv\Reader;
// 从上传文件读取CSV
$file = request()->file('import_file');
$csv = Reader::createFromPath($file->getPathname(), 'r');
$csv->setHeaderOffset(0); // 第一行为表头
foreach ($csv as $record) {
// $record 是关联数组
$data[] = [
'name' => $record['Name'],
'email' => $record['Email'],
'created_at' => now(),
'updated_at' => now(),
];
}
从API获取
use Illuminate\Support\Facades\Http;
$response = Http::timeout(30)->retry(3, 100)->get('https://api.example.com/data');
$records = $response->json();
从数据库连接
// 在config/database.php配置外部数据库连接
$users = DB::connection('external_db')
->table('users')
->where('updated_at', '>', $lastSync)
->get();
数据清洗与验证
使用 Laravel Validation
use Illuminate\Support\Facades\Validator;
$rules = [
'*.name' => 'required|string|max:255',
'*.email' => 'required|email|unique:users,email',
'*.age' => 'nullable|integer|min:0|max:150',
];
$validator = Validator::make($data, $rules);
if ($validator->fails()) {
// 收集错误信息
$errors = $validator->errors()->all();
Log::warning('Import validation failed', ['errors' => $errors]);
return back()->withErrors($validator);
}
数据转换与清洗
$cleanData = collect($rawData)->map(function ($item) {
return [
'name' => trim($item['name'] ?? ''),
'email' => strtolower(trim($item['email'] ?? '')),
'amount' => (float) str_replace(['$', ','], '', $item['amount']),
'status' => in_array($item['status'], ['active', 'inactive']) ? $item['status'] : 'unknown',
];
});
批量插入与更新
批量插入(性能最优)
// 每次插入1000条
$chunks = array_chunk($cleanData, 1000);
foreach ($chunks as $chunk) {
User::insert($chunk);
}
UPSERT(存在则更新,不存在则插入)
use Illuminate\Support\Facades\DB;
// 基于email字段判断重复
DB::table('users')->upsert(
$cleanData,
['email'], // 唯一键
['name', 'phone', 'updated_at'] // 需要更新的字段
);
使用 firstOrCreate / updateOrCreate
foreach ($cleanData as $data) {
User::updateOrCreate(
['email' => $data['email']],
$data
);
}
队列处理(推荐大量数据)
创建 Job
// app/Jobs/ImportUsersJob.php
class ImportUsersJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $chunk;
public function __construct(array $chunk)
{
$this->chunk = $chunk;
}
public function handle()
{
DB::transaction(function () {
foreach ($this->chunk as $row) {
User::create($row);
}
});
}
public function failed(\Throwable $exception)
{
Log::error('Import chunk failed', [
'error' => $exception->getMessage(),
'chunk' => $this->chunk
]);
}
}
// 使用
$chunks = array_chunk($cleanData, 500);
foreach ($chunks as $chunk) {
ImportUsersJob::dispatch($chunk);
}
完整示例:CSV导入控制器
<?php
namespace App\Http\Controllers;
use App\Jobs\ImportUsersJob;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use League\Csv\Reader;
class ImportController extends Controller
{
public function importUsers(Request $request)
{
// 1. 验证上传文件
$request->validate([
'file' => 'required|file|mimes:csv,txt|max:10240',
]);
try {
// 2. 读取CSV
$csv = Reader::createFromPath($request->file('file')->getPathname(), 'r');
$csv->setHeaderOffset(0);
$records = [];
$errors = [];
$rowNumber = 0;
// 3. 逐行处理
foreach ($csv as $row) {
$rowNumber++;
// 验证单行数据
$validator = Validator::make($row, [
'name' => 'required|string|max:255',
'email' => 'required|email',
]);
if ($validator->fails()) {
$errors[] = "Row {$rowNumber}: " . implode(', ', $validator->errors()->all());
continue;
}
$records[] = [
'name' => trim($row['name']),
'email' => strtolower(trim($row['email'])),
'phone' => $row['phone'] ?? null,
'created_at' => now(),
'updated_at' => now(),
];
}
// 4. 批量导入(使用队列或直接插入)
if (!empty($records)) {
$chunks = array_chunk($records, 500);
foreach ($chunks as $chunk) {
ImportUsersJob::dispatch($chunk);
}
}
// 5. 返回结果
return response()->json([
'success' => true,
'imported' => count($records),
'errors' => $errors,
'message' => count($records) . ' records queued for import'
]);
} catch (\Exception $e) {
Log::error('Import failed: ' . $e->getMessage());
return response()->json([
'success' => false,
'message' => 'Import failed: ' . $e->getMessage()
], 500);
}
}
}
推荐包
- Maatwebsite/Laravel-Excel:强大的Excel/CSV处理,支持导入、导出、批量验证
- Laravel-Excel 导入示例:
use Maatwebsite\Excel\Facades\Excel; use App\Imports\UsersImport;
Excel::import(new UsersImport, $request->file('file'));
## 7. 关键注意事项
1. **内存管理**:大文件使用`lazyCollection()`或队列分块处理
2. **事务处理**:每块数据使用独立事务,避免全部回滚
3. **错误处理**:记录错误行,允许部分导入成功
4. **唯一约束**:使用`upsert`或先查询后插入
5. **性能监控**:记录导入时间、数量、失败原因
6. **用户反馈**:提供进度条或异步通知
##
| 场景 | 推荐方案 |
|------|----------|
| 小数据量 (<1000) | 直接同步插入 + 验证 |
| 中等数据量 (1000-10000) | 批量chunk插入 + 事务 |
| 大数据量 (>10000) | 队列分片处理 + 事务 |
| 需要更新已有数据 | `upsert` 或 `updateOrCreate` |
| 复杂格式(Excel) | Maatwebsite/Laravel-Excel |
选择方案时,根据数据量大小、实时性要求和错误容忍度来决定是同步处理还是异步队列处理。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播