Installation
composer require turbostream/export-engine
Publish the config file:
php artisan vendor:publish --provider="TurboStream\ExportEngine\ExportEngineServiceProvider"
Basic Export (CSV Example)
use TurboStream\ExportEngine\Facades\ExportEngine;
$export = ExportEngine::query(YourModel::class)
->select(['id', 'name', 'email'])
->export('csv');
First Use Case: Quick CSV Export
$export = ExportEngine::query(User::class)
->select(['id', 'name', 'created_at'])
->export('csv', 'users_export_' . now()->format('Y-m-d'));
// Process 15K records per chunk (adjustable via config)
$export = ExportEngine::query(Product::class)
->chunk(15000)
->select(['sku', 'price', 'stock'])
->export('xlsx');
cursor() for memory efficiency (default behavior).chunk_size in config/export-engine.php.$export = ExportEngine::query(Order::class)
->select(['order_id', 'customer', 'total'])
->pdf()
->setTitle('Yearly Orders Report')
->addSubtotal('total', 'SUM', 'quarter')
->addGrandTotal('total', 'SUM')
->export();
setTitle(): PDF title/header.addSubtotal(): Group subtotals (e.g., by quarter).addGrandTotal(): Summarize entire dataset.setColumnWidths(): Customize PDF column widths.// Dispatch to queue (uses Redis by default)
$export = ExportEngine::query(Transaction::class)
->select(['date', 'amount', 'status'])
->export('pdf', 'transactions_report', true); // 3rd param = async
TurboStream\ExportEngine\Jobs\ExportJob.$status = ExportEngine::status('transactions_report');
if ($status->completed) {
return redirect($status->downloadUrl);
}
$export = ExportEngine::query(Invoice::class)
->select(['invoice_number', 'client', 'amount'])
->setHeaders([
'invoice_number' => 'Invoice #',
'client' => 'Client Name',
'amount' => 'Amount ($)',
])
->export('docx');
$export = ExportEngine::query(Post::class)
->select('*')
->sql()
->setFileName('posts_backup_' . now()->format('Y-m-d'))
->export();
.sql file with INSERT statements.use TurboStream\ExportEngine\Facades\ExportEngine;
Route::get('/export-users', function () {
return ExportEngine::query(User::class)
->select(['id', 'name', 'email'])
->export('csv');
});
@if(ExportEngine::status($exportId)->pending)
<a href="{{ route('export.status', $exportId) }}">Check Status</a>
@elseif(ExportEngine::status($exportId)->completed)
<a href="{{ ExportEngine::status($exportId)->downloadUrl }}">Download</a>
@endif
public function testExport()
{
$export = ExportEngine::query(User::class)
->select(['id', 'name'])
->export('csv');
// Assert file was generated (check storage/temp)
$this->assertFileExists(storage_path('app/temp/users_export_'.now()->format('Y-m-d').'.csv'));
}
Memory Leaks with Large Datasets
cursor() or setting an overly large chunk_size.cursor() for datasets >10K records. Configure chunk_size in config/export-engine.php (default: 10,000).
'chunk_size' => env('EXPORT_CHUNK_SIZE', 15000),
PDF Generation Timeouts
max_execution_time.export('pdf', 'filename', true)) or increase max_execution_time in php.ini temporarily.Queue Failures
queue:work is running:
php artisan queue:work --daemon
failed_jobs table for errors:
php artisan queue:failed-table
Column Width Issues in PDF
setColumnWidths() or adjust font size:
->pdf()
->setColumnWidths([10, 50, 30]) // widths in mm
->setFontSize(8)
SQL Export Quirks
setSqlEscape(true):
->sql()
->setSqlEscape(true)
Log Export Progress
Enable debug logs in config/export-engine.php:
'debug' => env('EXPORT_DEBUG', false),
storage/logs/export-engine.log.Check Temp Files
storage/app/temp/ before download.Validate Query Test your query manually first:
YourModel::cursor()->take(10)->get(); // Check for errors
Async Export Status
$status = ExportEngine::status('export_id');
// $status->progress (0-100), $status->completed, $status->error
Custom Export Formats
Extend the TurboStream\ExportEngine\Contracts\ExportFormat interface:
class CustomFormat implements ExportFormat {
public function generate(array $data, string $fileName) { ... }
}
Register in config/export-engine.php:
'formats' => [
'custom' => \App\Exports\CustomFormat::class,
],
Override Default Styling Publish and modify the PDF/DOCX templates:
php artisan vendor:publish --tag=export-engine-views
resources/views/vendor/export-engine/.Hooks for Pre/Post Processing Use events:
// In EventServiceProvider
ExportEngine::exporting(function ($export) {
// Modify data before export
});
ExportEngine::exported(function ($export) {
// Cleanup after export
});
Custom Chunk Processing Override chunk logic for complex data:
$export = ExportEngine::query(ComplexModel::class)
->setChunkProcessor(function ($chunk) {
return $chunk->map(fn ($item) => [
'id' => $item->id,
'processed_data' => $this->process($item),
]);
})
->export('csv');
Database Indexes
Ensure select() columns are indexed for faster queries.
Queue Batch Size
Adjust queue_batch_size in config to balance memory/CPU:
'queue_batch_size' => 5, // Process 5 jobs at once
Storage Engine
For async exports, use a fast storage driver (e.g., local or s3):
'storage_disk' => 's3',
Disable Logging in Production
'debug'
How can I help you explore Laravel packages today?