Laravel

PDF & Excel Export

Export data as PDF using barryvdh/laravel-dompdf and as Excel/CSV using maatwebsite/excel. Covers installation, Export class creation, collection binding, headings, and download/stream responses.

Install DomPDF: Add barryvdh/laravel-dompdf via Composer. Laravel auto-discovers the service provider.
📄terminal
BASH
composer require barryvdh/laravel-dompdf

# Optionally publish the config
php artisan vendor:publish --provider="Barryvdh\DomPDF\ServiceProvider"
Generate PDF from a Blade View: Use the Pdf facade to load a view with data, then return it as a download or stream it inline to the browser.
📄app/Http/Controllers/ReportController.php
PHP
<?php

namespace App\Http\Controllers;

use Barryvdh\DomPDF\Facade\Pdf;
use App\Models\Order;

class ReportController extends Controller
{
    // Force browser to download the PDF
    public function downloadPdf($id)
    {
        $order = Order::with('items.product', 'user')->findOrFail($id);

        $pdf = Pdf::loadView('pdf.invoice', ['order' => $order])
                  ->setPaper('a4', 'portrait');

        return $pdf->download("invoice-{$order->id}.pdf");
    }

    // Stream PDF inline in the browser
    public function streamPdf($id)
    {
        $order = Order::with('items.product', 'user')->findOrFail($id);

        $pdf = Pdf::loadView('pdf.invoice', ['order' => $order])
                  ->setPaper('a4', 'portrait');

        return $pdf->stream("invoice-{$order->id}.pdf");
    }
}
PDF Blade Template: Create a simple Blade view for DomPDF to render. Keep styles inline — DomPDF has limited CSS support.
📄resources/views/pdf/invoice.blade.php
HTML
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Invoice #{{ $order->id }}</title>
    <style>
        body  { font-family: sans-serif; font-size: 13px; color: #333; }
        table { width: 100%; border-collapse: collapse; margin-top: 16px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background: #f5f5f5; }
        .total { text-align: right; font-weight: bold; margin-top: 12px; }
    </style>
</head>
<body>
    <h2>Invoice #{{ $order->id }}</h2>
    <p>Customer: {{ $order->user->name }} &lt;{{ $order->user->email }}&gt;</p>
    <p>Date: {{ $order->created_at->format('d M Y') }}</p>

    <table>
        <thead>
            <tr><th>#</th><th>Product</th><th>Qty</th><th>Price</th><th>Subtotal</th></tr>
        </thead>
        <tbody>
            @foreach($order->items as $i => $item)
            <tr>
                <td>{{ $i + 1 }}</td>
                <td>{{ $item->product->name }}</td>
                <td>{{ $item->qty }}</td>
                <td>Rp {{ number_format($item->price, 0, ',', '.') }}</td>
                <td>Rp {{ number_format($item->price * $item->qty, 0, ',', '.') }}</td>
            </tr>
            @endforeach
        </tbody>
    </table>
    <p class="total">Total: Rp {{ number_format($order->total_price, 0, ',', '.') }}</p>
</body>
</html>
Install Maatwebsite Excel: Add maatwebsite/excel via Composer, then publish the config file.
📄terminal
BASH
composer require maatwebsite/excel

php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider" --tag=config
Create an Export Class: Generate an Export class with Artisan. Implement FromCollection to supply data and WithHeadings to add a header row.
📄terminal
BASH
php artisan make:export UsersExport --model=User
📄app/Exports/UsersExport.php
PHP
<?php

namespace App\Exports;

use App\Models\User;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;

class UsersExport implements
    FromCollection,
    WithHeadings,
    WithMapping,
    ShouldAutoSize
{
    public function collection()
    {
        return User::select('id', 'name', 'email', 'created_at')
                   ->orderBy('id')
                   ->get();
    }

    public function headings(): array
    {
        return ['#', 'Full Name', 'Email Address', 'Registered At'];
    }

    public function map($user): array
    {
        return [
            $user->id,
            $user->name,
            $user->email,
            $user->created_at->format('d/m/Y H:i'),
        ];
    }
}
Export with Constructor Filter: Pass parameters to the Export class constructor to filter data dynamically, e.g., by date range.
📄app/Exports/OrdersExport.php
PHP
<?php

namespace App\Exports;

use App\Models\Order;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;

class OrdersExport implements FromQuery, WithHeadings, ShouldAutoSize
{
    public function __construct(
        protected string $from,
        protected string $to
    ) {}

    public function query()
    {
        return Order::with('user')
            ->whereBetween('created_at', [$this->from, $this->to])
            ->select('id', 'user_id', 'total_price', 'payment_status', 'created_at');
    }

    public function headings(): array
    {
        return ['Order ID', 'Customer', 'Total', 'Status', 'Date'];
    }
}
Download Excel or CSV in Controller: Use the Excel facade's download() method. Pass Xlsx::class, Csv::class, or Pdf::class as the writer type.
📄app/Http/Controllers/ReportController.php
PHP
<?php

namespace App\Http\Controllers;

use Maatwebsite\Excel\Facades\Excel;
use App\Exports\UsersExport;
use App\Exports\OrdersExport;
use Illuminate\Http\Request;

class ReportController extends Controller
{
    // Download users as .xlsx
    public function exportUsers()
    {
        return Excel::download(new UsersExport(), 'users.xlsx');
    }

    // Download users as .csv
    public function exportUsersCsv()
    {
        return Excel::download(new UsersExport(), 'users.csv', \Maatwebsite\Excel\Excel::CSV);
    }

    // Download orders filtered by date range
    public function exportOrders(Request $request)
    {
        $request->validate([
            'from' => 'required|date',
            'to'   => 'required|date|after_or_equal:from',
        ]);

        $filename = "orders-{$request->from}-to-{$request->to}.xlsx";

        return Excel::download(
            new OrdersExport($request->from, $request->to),
            $filename
        );
    }
}
Export Routes: Register the export endpoints in routes/web.php behind auth middleware.
📄routes/web.php
PHP
use App\Http\Controllers\ReportController;

Route::middleware('auth')->prefix('export')->group(function () {
    Route::get('/invoice/{order}',  [ReportController::class, 'downloadPdf']);
    Route::get('/invoice-view/{order}', [ReportController::class, 'streamPdf']);
    Route::get('/users',            [ReportController::class, 'exportUsers']);
    Route::get('/users/csv',         [ReportController::class, 'exportUsersCsv']);
    Route::get('/orders',            [ReportController::class, 'exportOrders']);
});