Import data dari file Excel ke database adalah kebutuhan yang sangat umum dalam aplikasi bisnis โ mulai dari import data produk, data karyawan, hingga data transaksi. Laravel tidak memiliki fitur ini secara bawaan, namun ada package populer bernama Laravel Excel (by Maatwebsite) yang sangat mudah digunakan dan kaya fitur. Tutorial ini akan memandu kamu dari instalasi hingga import dengan validasi data.
Instalasi Laravel Excel
Install package menggunakan Composer:
composer require maatwebsite/excel
Untuk Laravel 11, service provider dan facade akan terdaftar otomatis. Untuk Laravel 10 ke bawah, publish konfigurasi opsional:
php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider" --tag=config
Pastikan ekstensi PHP berikut aktif (biasanya sudah aktif secara default):
php_zipphp_xmlphp_gd2
Menyiapkan Model dan Migration
Contoh kasus: import data produk dari Excel.
php artisan make:model Product -m
// Migration
public function up(): void
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('sku')->unique();
$table->string('name');
$table->string('category')->nullable();
$table->decimal('price', 12, 2);
$table->integer('stock')->default(0);
$table->timestamps();
});
}
php artisan migrate
Membuat Kelas Import
php artisan make:import ProductsImport --model=Product
Edit app/Imports/ProductsImport.php:
<?php
namespace App\Imports;
use App\Models\Product;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\SkipsOnError;
use Maatwebsite\Excel\Concerns\SkipsErrors;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
class ProductsImport implements
ToModel,
WithHeadingRow,
WithValidation,
SkipsOnError,
WithBatchInserts,
WithChunkReading
{
use SkipsErrors;
// Baca Excel per 1000 baris agar hemat memori
public function chunkSize(): int
{
return 1000;
}
// Insert ke DB dalam batch
public function batchSize(): int
{
return 500;
}
public function model(array $row): ?Product
{
return new Product([
'sku' => trim($row['sku']),
'name' => trim($row['nama_produk']),
'category' => $row['kategori'] ?? null,
'price' => (float) str_replace(['.', ','], ['', '.'], $row['harga']),
'stock' => (int) $row['stok'],
]);
}
// Validasi per baris
public function rules(): array
{
return [
'sku' => 'required|string|max:50',
'nama_produk' => 'required|string|max:255',
'harga' => 'required',
'stok' => 'required|integer|min:0',
];
}
// Pesan error kustom
public function customValidationMessages(): array
{
return [
'sku.required' => 'Kolom SKU wajib diisi.',
'nama_produk.required' => 'Kolom nama produk wajib diisi.',
'harga.required' => 'Kolom harga wajib diisi.',
];
}
}
Membuat Controller dan Route
php artisan make:controller ImportController
<?php
namespace App\Http\Controllers;
use App\Imports\ProductsImport;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
class ImportController extends Controller
{
public function index()
{
return view('import.index');
}
public function store(Request $request)
{
$request->validate([
'file' => 'required|file|mimes:xlsx,xls,csv|max:10240',
]);
$import = new ProductsImport();
Excel::import($import, $request->file('file'));
$failures = $import->failures();
$errors = $import->errors();
if ($failures->isNotEmpty() || ! empty($errors)) {
$errorMessages = [];
foreach ($failures as $failure) {
$errorMessages[] = "Baris {$failure->row()}: " . implode(', ', $failure->errors());
}
return back()->with('import_errors', $errorMessages)
->with('warning', 'Import selesai dengan beberapa error.');
}
return back()->with('success', 'Data berhasil diimport!');
}
}
// routes/web.php
use App\Http\Controllers\ImportController;
Route::get('/import', [ImportController::class, 'index'])->name('import.index');
Route::post('/import', [ImportController::class, 'store'])->name('import.store');
Membuat View Form Upload
<!-- resources/views/import/index.blade.php -->
@if(session('success'))
<div style="color:green">{{ session('success') }}</div>
@endif
@if(session('warning'))
<div style="color:orange">{{ session('warning') }}</div>
<ul>
@foreach(session('import_errors', []) as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
<form action="{{ route('import.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<p>Format file: .xlsx atau .csv</p>
<p>Kolom yang dibutuhkan: sku, nama_produk, kategori, harga, stok</p>
<input type="file" name="file" accept=".xlsx,.xls,.csv">
@error('file') <p style="color:red">{{ $message }}</p> @enderror
<button type="submit">Import Sekarang</button>
</form>
Format Template Excel
Pastikan file Excel yang diupload memiliki baris pertama sebagai header (karena kita pakai WithHeadingRow). Contoh struktur kolom:
- Kolom A:
sku - Kolom B:
nama_produk - Kolom C:
kategori - Kolom D:
harga - Kolom E:
stok
Laravel Excel secara otomatis mengkonversi header menjadi lowercase dan mengganti spasi dengan underscore.
Kesimpulan
Dengan package Laravel Excel, proses import data dari file Excel menjadi sangat mudah dan terstruktur. Gunakan WithChunkReading dan WithBatchInserts untuk file yang besar agar tidak terjadi memory exhausted. Selalu sertakan validasi dan penanganan error agar user mendapat informasi yang jelas jika ada baris yang bermasalah. Kamu juga bisa mengembangkan fitur ini dengan menambahkan export data menggunakan kelas yang sama dari Laravel Excel.