Import XLS, XLSX and CSV File into MySQL Database Using Laravel Application
Laravel Version: 10.20.0
PHP Version: 8.2.4
Requirements
PHP: ^7.2\|^8.0
Laravel: ^5.8
PhpSpreadsheet: `^1.21
PHP extension php_zip enabled
PHP extension php_xml enabled
PHP extension php_gd2 enabled
PHP extension php_iconv enabled
PHP extension php_simplexml enabled
PHP extension php_xmlreader enabled
PHP extension php_zlib enabled
maatwebsite/excel 3.1
Step 1: Create Laravel project with below command in the terminal
composer create-project laravel/laravel import_xls_xlsx_csv_files_to_mysql
Step 2: Now let's create database migration using below artisan command:
php artisan make:migration create_employee_table
Step 3: Now add table fields in the migration class in the up() method.
Schema::create('employee', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name', 200);
$table->integer('age', );
$table->date('doj');
$table->timestamps();
});
Step 4: Run the migrate command to generate table in the database:
php artisan migrate
Step 5: create model using following command:
php artisan make:model Employee
Step 6: Add following code into your Employee Model
protected $table="employee";
protected $fillable = ['name','age','doj'];
Step 7: Package Installation
composer require maatwebsite/excel
The Maatwebsite\Excel\ExcelServiceProvider is auto-discovered and registered by default.
If you want to register it yourself, add the ServiceProvider in config/app.php:
'providers' => [
/*
* Package Service Providers...
*/
Maatwebsite\Excel\ExcelServiceProvider::class,
]
The Excel facade is also auto-discovered.
If you want to add it manually, add the Facade in config/app.php:
'aliases' => [
...
'Excel' => Maatwebsite\Excel\Facades\Excel::class,
]
To publish the config, run the vendor publish command:
php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider" --tag=config
This will create a new config file named config/excel.php.
Step 8: Create an import class in app/Imports
You may do this by using the make:import command.
php artisan make:import EmployeeImport --model=Employee
php artisan make:import EmployeeCSVImport --model=Employee
The File can be found in app/Imports
.
├── app
│ ├── Imports
│ │├── EmployeeImport.php
│ │├── EmployeeCSVImport.php
│
└── composer.json
Step 9: Create new controller
php artisan make:controller EmployeeController
Add Following Traits:
use App\Models\Employee;
use App\Imports\{EmployeesImport,EmployeeCSVImport};
use Maatwebsite\Excel\Facades\Excel;
use Exception;
Step 10: In Controller (For Form Action)
public function index()
{
return view('welcome');
}
Step 11: Call Import Function From EmployeeController
public function store(Request $request)
{
try{
if ($request->hasFile('bulk_employee_records')) {
switch ($request->file('bulk_employee_records')->clientExtension()) {
case "xlsx":
Excel::import(new EmployeesImport, $request->file('bulk_employee_records'));
return redirect('/')->with('success', 'All good!');
case "xls":
Excel::import(new EmployeesImport, $request->file('bulk_employee_records'));
return redirect('/')->with('success', 'All good!');
case "csv":
Excel::import(new EmployeeCSVImport, $request->file('bulk_employee_records'));
return redirect('/')->with('success', 'All good!');
default:
throw new \Exception('Invalid file format');
}
}
}
catch(Exception $e) {
return redirect('/')->with('error',$e->getMessage());
}
catch(\Maatwebsite\Excel\Validators\ValidationException $ve){
return redirect('/')->with('error',$ve->failures());
}
}
Step 12: View Blade File (welcome.blade.php)
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-3">
@include('flash-message')
<form action="{{ route('store_employee_records') }}" method="post" enctype="multipart/form-data">
@csrf
<div class="mb-3 mt-3">
<label for="email">File:</label>
<input type="file" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel,text/comma-separated-values, text/csv, application/csv" required class="form-control" name="bulk_employee_records">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Step 12: Open EmployeesImport (App/Import/) and Add following code
<?php
namespace App\Imports;
use App\Models\Employee;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
class EmployeesImport implements ToModel, WithChunkReading, SkipsEmptyRows, WithHeadingRow, WithBatchInserts
{
use Importable;
/**
* @param array $employeeRecords
*
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $employeeRecords)
{
return new Employee([
'name' => $employeeRecords['name'],
'age' => $employeeRecords['age'],
'doj' => \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($employeeRecords['doj'])
]);
}
//In case your heading row is not on the first row, you can easily specify this in your import class:
public function headingRow(): int
{
return 1;
}
//Chunk reading : increase in memory usage (Importing a large file can have a huge impact on the memory usage)
public function chunkSize(): int
{
return 1000;
}
//Importing a large file to Eloquent models, might quickly become a bottleneck as every row results into an insert query.
// limit the amount of queries done by specifying a batch size
//This concern only works with the ToModel concern.
public function batchSize(): int
{
return 1000;
}
}
Step 13: Open EmployeesCSVImport (App/Import/) and Add following code
<?php
namespace App\Imports;
use App\Models\Employee;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
class EmployeeCSVImport implements ToModel,WithChunkReading, SkipsEmptyRows, WithHeadingRow, WithBatchInserts
{
/**
* @param array $row
*
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $employeeRecords)
{
return new Employee([
'name' => $employeeRecords['name'],
'age' => $employeeRecords['age'],
'doj' => date('Y-m-d',strtotime($employeeRecords['doj']))
]);
}
//In case your heading row is not on the first row, you can easily specify this in your import class:
public function headingRow(): int
{
return 1;
}
//Chunk reading : increase in memory usage (Importing a large file can have a huge impact on the memory usage)
public function chunkSize(): int
{
return 1000;
}
//Importing a large file to Eloquent models, might quickly become a bottleneck as every row results into an insert query.
// limit the amount of queries done by specifying a batch size
//This concern only works with the ToModel concern.
public function batchSize(): int
{
return 1000;
}
}
Step 14: Route
use App\Http\Controllers\EmployeeController;
Route::get('/',[EmployeeController::class,'index']);
Route::post('/',[EmployeeController::class,'store'])->name('store_employee_records');
Step 15: Clear the cache
php artisan optimize:clear
Step 16: Run the application
php artisan serve