Salah satu keperluan dalam aplikasi web pada masa kini ialah keupayaan menjana output dalam format PDF, terutama sekali apabila melibatkan operasi menjana laporan dan statistik. Satu masa dahulu, tugasan ini amat membebankan pengaturcara, tetapi dengan adanya Composer dan Packagist, mencari pakej yang sesuai hanya mengambil masa beberapa minit sahaja.

Kali ini kita akan lihat bagaimana menggunakan pakej DOMPDF Wrapper dari Barry vd. Heuvel untuk menjana output dalam format PDF menggunakan Laravel 4.2.

Langkah 1

Dengan menggunakan Terminal atau Command, taipkan arahan berikut:

composer require --prefer-dist "barryvdh/laravel-dompdf:0.4.*"

Composer akan memuat-turun semua fail-fail pakej dan juga dependencies pakej ini di dalam aplikasi Laravel kita.

Composer memuat-turun fail-fail pakej DOMPDF Wrapper for Laravel

Langkah 2

Sekarang kita perlu register pakej ini di dalam Laravel. Buka fail /app/config/app.php, dan tambahkan kod seperti yang ditunjukkan di bawah ini di bahagian providers:

'BarryvdhDomPDFServiceProvider',

Kemudian, kita akan tambahkan kod berikut pada bahagian aliases pula:

'PDF' => 'BarryvdhDomPDFFacade',

Sekarang kita telah bersedia untuk menggunakan pakej ini di dalam aplikasi kita.

Langkah 3

Untuk setiap fail PDF yang ingin dijana, saya lebih suka menggunakan layout yang berlainan daripada yang digunakan pada view yang sedia ada, ini bagi membolehkan saya menetapkan styling yang sesuai untuk PDF itu sahaja.

Jadi, kita akan cipta satu fail layout baru di /app/views/layouts/pdf.blade.php, kemudian masukkan kod berikut:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>@yield('page-title', 'PDF Document')</title>
    </head>
    <body>
        @yield('content')
    </body>
</html>

Pada layout ini, kita mempunyai 2 section, iaitu:

  1. page-title
    Digunakan untuk menetapkan tajuk dokumen. Di sini juga kita menetapkan nilai asas yang akan digunakan sekiranya kita terlupa untuk assign sebarang value pada section ini.
  2. content
    Digunakan sebagai isi kandungan layout. Ia merupakan lokasi isi kandungan fail PDF kita nanti.

Langkah 4

Sekarang semua persediaan telah sedia digunakan, kita perlukan data untuk dimasukkan di dalam fail PDF ini. Sebagai contoh, saya ingin menjana satu laporan untuk semua pengguna yang berada di dalam sistem dan paparan yang saya inginkan adalah seperti berikut:

sample-report-interfaceNota:
Sila abaikan maklumat pengguna yang berulang, ini untuk tujuan perancangan rekabentuk sahaja.

Jadi, dengan menggunakan rekabentuk di atas, kita boleh hasilkan view yang khas untuk laporan ini. Salin kod berikut dan letakkan pada fail /app/views/reports/users.blade.php.

@extends('layouts.pdf')

@section('content')

    <div style="text-align: center">
        <header>
            <h1>HANASAKI SDN BHD</h1>
            <p>No 178 Jalan Restu 22, Taman Seri Puteri<br>
                Fasa II Meru Off Jalan Kassim, Kapar.<br>
                Tel: +603-333666789  Fax: +603-333666790</p>
        </header>
    </div>

    <div>
        <h2 style="text-align: center">LAPORAN SENARAI PENGGUNA SISTEM</h2>
        <hr>

        @if ($users->count())
            <table style="width: 100%;" cellpadding="5" cellspacing="3">
                <thead>
                    <tr>
                        <th>Nama</th>
                        <th>Emel</th>
                        <th>Kumpulan</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach ($users as $user)
                    <tr>
                        <td>{{{ $user->name }}}</td>
                        <td>{{{ $user->email }}}</td>
                        <td>{{{ $user->group->name }}}</td>
                    </tr>
                    @endforeach
                </tbody>
                <tfoot>
                    <tr>
                        <td colspan="3" class="text-center">
                            Jumlah Pengguna Sistem: <strong>{{ $users->count() }} orang</strong>
                        </td>
                    </tr>
                </tfoot>
            </table>
        @else
            <div class="alert alert-info text-center">Tiada Maklumat Untuk Dipaparkan</div>
        @endif
    </div>

@stop

Nota:
View ini sebenarnya boleh kita abstrakkan lagi untuk mudah digunakan oleh laporan lain, tetapi untuk tutorial ini saya hasilkan spesifik untuk laporan pengguna sahaja.

Langkah 5

Apa yang kita perlukan sekarang ialah proses untuk mendapatkan senarai pengguna dan kemudian menjana output dalam format PDF. Untuk tutorial ini, saya hanya tambahkan satu route yang khusus untuk menjana laporan ini. Tetapi pada aplikasi sebenar, ia sepatutnya berada pada Controller yang sesuai.

Route::get('/laporan/pengguna', function() {
   $name  = 'Laporan-Pengguna-Sistem.pdf';
   $users = AppModelsUser::orderBy('name')->get();
   $pdf   = PDF::loadView('reports.users', compact('users'));
   
   return $pdf->download($name);
})->before('auth');

Jika anda ingin memaparkan fail PDF berkenaan (pada web browser yang support), anda boleh tukarkan dengan kod ini.

Route::get('/laporan/pengguna', function() {
   $users = AppModelsUser::orderBy('name')->get();
   $pdf   = PDF::loadView('reports.users', compact('users'));

   return $pdf->stream();
})->before('auth');

Selesai!

Berikut merupakan hasilnya pada komputer saya.

sample-output-dompdf

Pada output yang dijana, tiada sebarang styling yang saya masukkan, jadi hasilnya sama seperti laman web zaman Geocities dulu, jadi ianya menjadi tugas anda untuk menambah styling untuk output tersebut.

Kesimpulan

Mudah kan? Dengan adanya Composer dan Packagist, pengaturcara PHP boleh berkongsi pakej untuk kegunaan bersama dengan mudah dan cepat. Malahan, mengemaskini pakej yang dipasang juga sangat mudah, hanya menggunakan arahan berikut:

composer update

Kita hanya perlu belajar bagaimana menggunakan pakej tersebut melalui dokumentasi yang disediakan oleh pengeluar pakej berkenaan. Dan ingat, kod-kod sumber terbuka bergantung kepada kita sebagai pengguna untuk melaporkan sebarang masalah atau membuat penambahbaikan. Jika berlakunya sebarang masalah, perkara pertama yang anda perlu lakukan ialah melaporkannya kepada pengaturcara pakej berkenaan demi kebaikan bersama.

Isu Yang Diketahui

  1. DOMPdf tidak menyokong Bootstrap, lihat di sini: https://github.com/dompdf/dompdf/issues/631
  • thanks bro, betul-betul membantu! 🙂 xd button thumbs up lak huhu

  • Choirul fatoni

    mau tya klo print berdasarkan bulan apakah sama

    • sama juga, ianya bergantung kepada query untuk mendapatkan rekod dari database. contohnya, katakan kita mahu dapatkan senarai registered users dari tarikh yang dipilih:

      $startDate = ‘2014-01-01’;
      $endDate = ‘2015-12-31’;

      $users = AppModelsUser::whereBetween(‘created_at’, [$startDate, $endDate])->get();

      kod yang lain tetap sama.

      • sayaputra

        saya menjalankan
        AppModelUser Not found mas

        apa ada yang kurang??

        • Cuba buka fail User model, ada gunakan namespacing tak? Tengok statement:

          namespace AppModels;

          jika ada. Jika tiada, tukarkan AppModelsUser kepada User, itu sahaja.

          • Choirul fatoni

            ini kenapa kok data yang dalam di database tidak bisa masuk malah kosongan

            @if ($users->count()) <—- fungsi dari ini apa mas

            maav banya taya buat tugas akhir kuliah saya

          • fungsi itu untuk memeriksa sama ada record wujud atau tidak. boleh rujuk di sini:

            http://laravel.com/docs/4.2/queries#aggregates

          • fungsi itu untuk memeriksa sama ada terdapat rekod user dalam database, jika tiada akan return false.

      • Choirul fatoni

        AppModelsUser nya not foud

        apa ada yang kurang mas

        • Cuba buka fail User model, ada gunakan namespacing tak? Tengok statement:

          namespace AppModels;

          jika ada. Jika tiada, tukarkan AppModelsUser kepada User, itu sahaja.

          • Choirul fatoni

            udh bisa

            klo bikin kertas landscape gimna kan dalam bentuk portrait??

          • cuba guna statement ini:

            $pdf = PDF::loadView(‘reports.users’, compact(‘users’))->setPaper(‘a4’)->setOrientation(‘landscape’);

            boleh rujuk pada dokumentasi package di https://github.com/barryvdh/laravel-dompdf/tree/0.4