Kritim Yantra
Apr 18, 2025
CSV (Comma Separated Values) is one of the most common file formats used for importing and exporting tabular data. Whether you’re importing customer details, products, or reports, handling CSV files is a must-have feature in many web applications.
In this blog, we’ll walk through a step-by-step process to import a CSV file in Laravel 12 using the powerful Laravel Excel package.
Make sure you have the following setup before starting:
Although the package name is "Excel", it supports CSV, XLSX, and XLS file types.
Run this command to install the package:
composer require maatwebsite/excel
Laravel 12 will auto-discover the package, so you don’t need to register anything manually.
Suppose we want to import a list of products from a CSV file.
Generate a model and migration:
php artisan make:model Product -m
Edit the migration file:
// database/migrations/xxxx_xx_xx_create_products_table.php
public function up(): void
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('sku')->unique();
$table->decimal('price', 10, 2);
$table->integer('stock');
$table->timestamps();
});
}
Run the migration:
php artisan migrate
Laravel Excel uses import classes to handle file data.
php artisan make:import ProductsImport --model=Product
Now, open app/Imports/ProductsImport.php
and modify it:
namespace App\Imports;
use App\Models\Product;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
class ProductsImport implements ToModel, WithHeadingRow
{
public function model(array $row)
{
return new Product([
'name' => $row['name'],
'sku' => $row['sku'],
'price' => $row['price'],
'stock' => $row['stock'],
]);
}
}
The
WithHeadingRow
concern tells the importer to treat the first row of the CSV file as the column headers.
Generate the controller to handle form submission and import logic:
php artisan make:controller ProductImportController
Then update it:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Imports\ProductsImport;
use Maatwebsite\Excel\Facades\Excel;
class ProductImportController extends Controller
{
public function showForm()
{
return view('import-products');
}
public function import(Request $request)
{
$request->validate([
'file' => 'required|file|mimes:csv,txt'
]);
Excel::import(new ProductsImport, $request->file('file'));
return back()->with('success', 'Products imported successfully!');
}
}
Create a Blade view at resources/views/import-products.blade.php
:
<!DOCTYPE html>
<html>
<head>
<title>Import CSV in Laravel 12</title>
</head>
<body>
<h2>Import Products CSV</h2>
@if(session('success'))
<p style="color:green">{{ session('success') }}</p>
@endif
<form action="{{ route('products.import') }}" method="POST" enctype="multipart/form-data">
@csrf
<input type="file" name="file" accept=".csv" required>
<button type="submit">Import</button>
</form>
</body>
</html>
Add the necessary routes in routes/web.php
:
use App\Http\Controllers\ProductImportController;
Route::get('/import-products', [ProductImportController::class, 'showForm'])->name('products.form');
Route::post('/import-products', [ProductImportController::class, 'import'])->name('products.import');
Create a products.csv
file with the following structure:
name,sku,price,stock
iPhone 14,IPH14,999.99,50
Samsung Galaxy S22,SGS22,899.99,60
Google Pixel 7,PIX7,799.99,40
http://your-app.test/import-products
WithValidation
concern.SkipsEmptyRows
concern.WithBatchInserts
for performance.WithCustomCsvSettings
if your CSV uses ;
instead of ,
.public function getCsvSettings(): array
{
return [
'delimiter' => ';'
];
}
Error: Undefined offset: 0
→ Make sure your file has headers and you’re using WithHeadingRow
.
Error: mimes validation failed
→ Ensure your file has a .csv
or .txt
extension and you’ve added mimes:csv,txt
validation.
That’s it! 🎉 You’ve now built a simple yet powerful CSV import feature in Laravel 12. The Maatwebsite/Laravel-Excel
package gives you all the flexibility you need for data import.
You can now expand this by:
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google