Skip to content

Day 24 โ€” Export Data ke PDF dengan DomPDF โ€‹

Fase: 3 โ€” Fitur Lanjutan | Minggu: 5 | Hari: Kamis


๐ŸŽฏ Tujuan Hari Ini โ€‹

  • Menginstal dan mengkonfigurasi package Barryvdh DomPDF untuk Laravel.
  • Membuat view Blade khusus yang dioptimalkan untuk tampilan PDF.
  • Mengimplementasikan endpoint untuk mengunduh laporan peminjaman dalam format PDF.
  • Memahami perbedaan pendekatan PDF vs Excel dan kapan menggunakan masing-masing.

๐Ÿ“– Penjelasan: PDF vs Excel โ€” Kapan Menggunakan Mana? โ€‹

KriteriaPDFExcel
TujuanPresentasi, cetak resmiAnalisis, pivot, edit data
FormatTetap (tidak bisa diedit)Fleksibel
Cocok untukSurat, laporan formal, fakturRekap data, laporan operasional
Dikirim keKlien, pimpinan, arsipInternal tim, akunting

Untuk laporan peminjaman yang harus dicetak dan ditandatangani, PDF adalah pilihan tepat.


๐Ÿ”ง Step-by-Step โ€‹

Step 1: Install Package DomPDF โ€‹

bash
composer require barryvdh/laravel-dompdf

Publish konfigurasi:

bash
php artisan vendor:publish --provider="Barryvdh\DomPDF\ServiceProvider"

Step 2: Buat Blade View Khusus PDF โ€‹

Buat file view baru khusus untuk layout PDF. View ini harus menggunakan HTML murni dengan inline CSS karena DomPDF memiliki dukungan CSS yang terbatas.

html
{{-- resources/views/loans/pdf.blade.php --}}

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <title>Laporan Peminjaman Aset</title>
    <style>
        /* CSS harus inline atau dalam tag <style> */
        body {
            font-family: Arial, sans-serif;
            font-size: 12px;
            color: #333;
        }
        .header {
            text-align: center;
            border-bottom: 2px solid #333;
            padding-bottom: 10px;
            margin-bottom: 20px;
        }
        .header h1 {
            font-size: 18px;
            margin: 0;
        }
        .header p {
            margin: 4px 0;
            color: #555;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 15px;
        }
        th {
            background-color: #2d6a4f;
            color: white;
            padding: 8px;
            text-align: left;
            font-size: 11px;
        }
        td {
            padding: 7px 8px;
            border-bottom: 1px solid #ddd;
            font-size: 11px;
        }
        tr:nth-child(even) {
            background-color: #f5f5f5;
        }
        .badge-pending {
            background: #f0ad4e;
            color: white;
            padding: 2px 6px;
            border-radius: 3px;
        }
        .badge-returned {
            background: #5cb85c;
            color: white;
            padding: 2px 6px;
            border-radius: 3px;
        }
        .footer {
            margin-top: 20px;
            text-align: right;
            font-size: 10px;
            color: #888;
        }
        .summary-box {
            background: #e8f5e9;
            border: 1px solid #4caf50;
            padding: 10px;
            border-radius: 4px;
            margin-bottom: 15px;
        }
    </style>
</head>
<body>

    <div class="header">
        <h1>SIMAS โ€” Sistem Manajemen Aset Sederhana</h1>
        <p>Laporan Data Peminjaman Aset</p>
        <p>Dicetak: {{ now()->format('d F Y, H:i') }} WIB</p>
    </div>

    <div class="summary-box">
        <strong>Ringkasan:</strong>
        Total Peminjaman: <strong>{{ $loans->count() }}</strong> &nbsp;|&nbsp;
        Sedang Dipinjam: <strong>{{ $loans->where('status', 'pending')->count() }}</strong> &nbsp;|&nbsp;
        Sudah Dikembalikan: <strong>{{ $loans->where('status', 'returned')->count() }}</strong>
    </div>

    <table>
        <thead>
            <tr>
                <th>No.</th>
                <th>Nama Peminjam</th>
                <th>Aset yang Dipinjam</th>
                <th>Jml</th>
                <th>Tgl Pinjam</th>
                <th>Tgl Kembali</th>
                <th>Status</th>
            </tr>
        </thead>
        <tbody>
            @foreach ($loans as $i => $loan)
            <tr>
                <td>{{ $i + 1 }}</td>
                <td>{{ $loan->borrower_name }}</td>
                <td>{{ $loan->asset->name ?? '-' }}</td>
                <td>{{ $loan->quantity }}</td>
                <td>{{ $loan->loan_date->format('d/m/Y') }}</td>
                <td>{{ $loan->return_date ? $loan->return_date->format('d/m/Y') : '-' }}</td>
                <td>
                    @if ($loan->status === 'returned')
                        <span class="badge-returned">Dikembalikan</span>
                    @else
                        <span class="badge-pending">Dipinjam</span>
                    @endif
                </td>
            </tr>
            @endforeach
        </tbody>
    </table>

    <div class="footer">
        <p>Dokumen ini digenerate otomatis oleh sistem. Sahkan dengan tanda tangan pejabat berwenang.</p>
    </div>

</body>
</html>

Step 3: Tambahkan Route dan Logic PDF โ€‹

php
// routes/web.php

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

Route::get('/loans/export/pdf', function () {
    $loans = Loan::with('asset')->latest()->get();

    $pdf = Pdf::loadView('loans.pdf', ['loans' => $loans]);

    // Atur ukuran dan orientasi kertas
    $pdf->setPaper('a4', 'landscape'); // landscape untuk tabel yang lebar

    // Download langsung:
    return $pdf->download('laporan-peminjaman-' . date('Ymd') . '.pdf');

    // Atau tampilkan di browser (tidak download):
    // return $pdf->stream('laporan-peminjaman.pdf');
})->name('loans.export.pdf');

Step 4: Tambahkan Tombol Export PDF di Blade โ€‹

html
{{-- resources/views/loans/index.blade.php --}}

<div class="d-flex justify-content-between align-items-center mb-3">
    <h1>Riwayat Peminjaman</h1>
    <div class="d-flex gap-2">
        <a href="{{ route('loans.create') }}" class="btn btn-primary">
            + Catat Peminjaman
        </a>
        <a href="{{ route('loans.export.excel') }}" class="btn btn-success">
            <i class="bi bi-file-earmark-excel"></i> Excel
        </a>
        <a href="{{ route('loans.export.pdf') }}" class="btn btn-danger">
            <i class="bi bi-file-earmark-pdf"></i> PDF
        </a>
    </div>
</div>

๐Ÿงช Uji Coba Mandiri โ€‹

  • [ ] Kunjungi halaman /loans โ†’ klik tombol "PDF" โ†’ file .pdf ter-download.
  • [ ] Buka PDF โ†’ pastikan tabel tampil rapi, ada header institusi.
  • [ ] Pastikan badge status "Dipinjam" dan "Dikembalikan" tampil dengan warna yang berbeda.
  • [ ] Coba ubah orientasi dari landscape ke portrait โ†’ lihat perbedaannya.
  • [ ] Pastikan ringkasan di atas tabel menampilkan jumlah yang benar.

โš ๏ธ Keterbatasan DomPDF โ€‹

WARNING

DomPDF memiliki keterbatasan CSS yang perlu diketahui:

  • Tidak mendukung Flexbox dan CSS Grid.
  • Tidak mendukung external CSS (Bootstrap dari CDN tidak akan berfungsi).
  • Semua styling harus berada dalam tag <style> atau inline.
  • Gambar harus menggunakan path absolut (storage_path(...)) atau Base64.

Cara Menampilkan Gambar di PDF (Jika Diperlukan) โ€‹

php
// Untuk menampilkan gambar di PDF, konversi ke Base64
$imagePath = storage_path('app/public/' . $asset->photo);
$imageData = base64_encode(file_get_contents($imagePath));
$imageMime = mime_content_type($imagePath);
$imageBase64 = 'data:' . $imageMime . ';base64,' . $imageData;
html
{{-- Di view PDF --}}
<img src="{{ $imageBase64 }}" width="80">

TIP

Untuk PDF yang lebih kompleks dengan grafik dan chart, pertimbangkan menggunakan Browsershot (berbasis Puppeteer) atau layanan seperti wkhtmltopdf. Namun untuk laporan tabel sederhana, DomPDF sudah lebih dari cukup.

Program Magang SMK RPL โ€” Rekayasa Perangkat Lunak (2 Bulan)