maatwebsite/excel
Laravel Excel is a Laravel wrapper for PhpSpreadsheet that makes Excel/CSV exports and imports simple and fast. Export collections or queries with automatic chunking, handle large datasets efficiently, and integrate cleanly into your Laravel apps.
Installation:
composer require maatwebsite/excel
Publish config (optional but recommended):
php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider" --tag=config
First Export:
use Maatwebsite\Excel\Facades\Excel;
use App\Exports\UsersExport;
// In a controller
return Excel::download(new UsersExport);
First Import:
use Maatwebsite\Excel\Facades\Excel;
use App\Imports\UsersImport;
// In a controller
$import = new UsersImport;
Excel::import($import, request()->file('file'));
vendor/maatwebsite/excel/stubs/ (for generating export/import classes)Export a Collection to Excel:
php artisan make:export UsersExport --model=User
Edit the generated UsersExport.php:
public function collection()
{
return User::all();
}
Use in a controller:
return Excel::download(new UsersExport);
public function collection()
{
return User::query()->where('active', 1)->get();
}
public function query()
{
return User::query()->where('active', 1);
}
public function view()
{
return view('users.table', ['users' => User::all()]);
}
public function model(array $row)
{
return new User([
'name' => $row['name'],
'email' => $row['email']
]);
}
use Maatwebsite\Excel\Concerns\WithChunkReading;
public function chunkSize(): int
{
return 1000;
}
Queue Exports:
use Maatwebsite\Excel\Concerns\WithQueueable;
public function queueable(): bool
{
return true;
}
Trigger via:
Excel::queue(new UsersExport);
Queue Imports:
Excel::queueImport(new UsersImport, request()->file('file'));
use Maatwebsite\Excel\Concerns\WithHeadings;
public function headings(): array
{
return [
'Name', 'Email', 'Role'
];
}
use Maatwebsite\Excel\Concerns\WithValidation;
public function rules(): array
{
return [
'email' => 'required|email',
'name' => 'required|min:3'
];
}
use Maatwebsite\Excel\Concerns\WithStyles;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
public function styles(Worksheet $sheet)
{
return [
1 => ['font' => ['bold' => true]],
];
}
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\AfterSheet;
public function registerEvents(): array
{
return [
AfterSheet::class => function(AfterSheet $event) {
// Custom logic after sheet creation
}
];
}
use Maatwebsite\Excel\Tests\TestCase;
public function testExport()
{
$this->assertExport($this->exportClass, 'users.xlsx');
}
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
use Maatwebsite\Excel\Concerns\WithTitle;
public function title(): string
{
return 'Users_' . now()->format('Y-m-d');
}
public function fileName(): string
{
return 'users_' . now()->format('Ymd') . '.xlsx';
}
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
public function sheets(): array
{
return [
new ActiveUsersExport,
new InactiveUsersExport
];
}
use Maatwebsite\Excel\Concerns\WithUpserts;
public function uniqueBy(): array
{
return ['email'];
}
public function updateModel($row, $original)
{
$original->name = $row['name'];
$original->save();
}
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
use Maatwebsite\Excel\Concerns\WithFormatData;
public function formatData(array $row)
{
$row['created_at'] = \Carbon\Carbon::parse($row['created_at'])->format('d/m/Y');
return $row;
}
Memory Limits:
chunkSize() or queue jobs.public function chunkSize(): int
{
return 500; // Adjust based on server memory
}
Time Zone Issues:
config/app.php has correct timezone. Excel exports may reflect server timezone by default.CSV Delimiters:
use Maatwebsite\Excel\Concerns\WithCustomCsvSettings;
public function getCsvSettings(): array
{
return [
'delimiter' => ';',
'enclosure' => '"',
'line_ending' => "\n",
'use_bom' => true,
'input_encoding' => 'UTF-8',
'output_encoding' => 'UTF-8'
];
}
Sheet Name Limitations:
use Maatwebsite\Excel\Concerns\WithTitle;
public function title(): string
{
return str_limit('Very Long Sheet Name', 31);
}
Empty Rows in Imports:
SkipsEmptyRows may skip rows with null values. Customize with:
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
public function isEmptyWhen($row, $key)
{
return empty($row[$key]) && $row[$key] !== '0';
}
Queue Failures:
failed() in your export/import class:
public function failed(\Throwable $e)
{
\Log::error('Export failed: ' . $e->getMessage());
// Notify admin via email, etc.
}
Log Rows During Import:
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
public function batchSize(): int
{
\Log::info('Processing batch');
return 100;
}
Inspect PhpSpreadsheet Object:
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\AfterSheet;
public function registerEvents(): array
{
return [
AfterSheet::class => function(AfterSheet $event) {
\Log::info($event->sheet->getTitle());
\Log::info($event->sheet->getHighestRow());
}
];
}
Test with Small Datasets:
->limit(10) in queries to debug before scaling up.Check Temporary Files:
php artisan excel:clean
use Maatwebsite\Excel\Concerns\
How can I help you explore Laravel packages today?