Laravel, PHP

Laravel| Export PDF

Một chức năng mà chúng ta rất hay gặp khi làm ứng dụng đó chính là xuất file PDF. Trong bài hôm nay mình sẽ hướng dẫn xuất PDF bằng pagekage barryvdh/laravel-dompdf.

1. Giới thiệu

laravel-dompdf là một DOMPDF Wrapper cho Laravel nghĩa là nó làm việc dựa trên core package là Dompdf HTML to PDF Converterlaravel-dompdf chính là package mở rộng giúp Laravelers dễ cài đặt và sử dụng hơn.

Về hỗ trợ của DomPDF thì được hỗ trợ CSS2 và một vài CSS3, với HTML thì chủ yếu là attributes của HTML4, hỗ trợ tốt cho các thẻ table (Xem thêm). Nói chung trong lúc thiết kế template cho PDF thì các bạn nên hạn chế sử dụng các attributes phức tạp và nên vừa thiết kế vừa xem kết quả PDF trực tiếp của mình luôn để còn dễ căn chỉnh chứ nếu cứ vẽ vời trên html xong một hồi quay lại kiểm tra trên PDF thật là thất vọng đấy =)).

2. Cài đặt

Để cài đặt laravel-dompdf tại terminal bạn chạy lệnh composer sau:

composer require barryvdh/laravel-dompdf

Tiếp theo đăng ký PDF cho provider alias cho PDF để ta có thể sử dụng PDF như là Facade.

Các bạn vào /config/app.php và thêm đoạn sau:

'providers' => [
    ....
    Barryvdh\DomPDF\ServiceProvider::class,
],
'aliases' => [
    ....
    'PDF' => Barryvdh\DomPDF\Facade::class,
],

Xong bước trên khi sử dụng để goi PDF trước tiên bạn cần import PDF như sau:

use PDF;

3. Tạo Controller

Tạo cho mình một action trong controller với method GET hay POST gì cũng được tùy bạn, sau đó tại action bạn dán đoạn code sau:

$arr = [1,2,3];
// load view blade PDF có kèm compact data như vẫn làm với view thông thường.
$pdf = PDF::loadView('pdf', compact('arr'));
// bạn có thể dùng hàm download() để tải file về luôn mà không cần preview
// 'disney.pdf' chính là tên file khi download, bạn có thể đặt tùy ý.
return $pdf->download('disney.pdf');
// hay bạn dùng stream() để có thể preview trước trên browser
// ở đây bạn có thể truyền tham số tên file pdf hoặc không
return $pdf->stream('my_file.pdf');

4. Tạo PDF view blade

Như phần controller trên ta có gọi loadview() với tên view là ‘pdf

PDF::loadView('pdf', compact('arr'));

Như vậy bạn cần tạo file pdf.blade.php tại thư mục resources/views/pdf.blade.php, nói chung như lúc bạn tạo view bình thường ))

Ở đây html mình thiết kế như sau:

<body>
    Welcome to my DomPDF.
    @foreach ($arr as $item)
        <div>{{ $item }}</div>
    @endforeach
</body>

Và kết quả

OK như vậy đến đây cơ bản là bạn đã có thể tạo ra PDF cho riêng mình rồi.

5. Thêm

5.1 Tùy chỉnh paper size

Để thay đổi paper size khi xuất PDF bạn làm như sau:

$pdf = PDF::loadView('pdf');
// thay A3 => A4, A5, ...
// 'landscape' => 'portrait'
$pdf->setPaper('A3', 'landscape');

5.2 Custom fonts

Khi bạn dùng tiếng Việt hoặc tiếng Nhật thì mặc định DomPDF không hỗ trợ mà bạn phải tự cài đặt thêm font.

Giả sử trong html của bạn

<body>
    Thương lắm em gái mưa.
</body>

Kết quả mặc định chưa thêm font là

Lỗi font

Để giải quyết vấn đề bạn cần tìm bộ font hỗ trợ tiếng Việt hoặc bất kỳ font có hỗ trợ ngôn ngữ bạn cần sau đó chép các file fonts xxx.ttf chép vào /storage/fonts.

Ở đây mình tải bộ font Notosans gồm những file sau:

Trọn bộ file fonts Notosans

Tiếp theo chép tất cả file font xxx.ttf chép vào /storage/fonts.

Chép vào /storage/fonts

Tại trang pdf.blade.php

<style type="text/css">
        @font-face {
            font-family: 'notosans-regular';
            src: url({{ storage_path('fonts\NotoSans-Regular.ttf')}}) format("truetype");
            font-weight: 400;
            font-style: normal;
        }
        @font-face {
            font-family: 'notosans-italic';
            src: url({{ storage_path('fonts\NotoSans-Italic.ttf')}}) format("truetype");
            font-weight: 400;
            font-style: italic;
        }
        @font-face {
            font-family: 'notosans-bold';
            src: url({{ storage_path('fonts\NotoSans-Bold.ttf')}}) format("truetype");
            font-weight: 700;
            font-style: normal;
        }
        @font-face {
            font-family: 'notosans-bolditalic';
            src: url({{ storage_path('fonts\NotoSans-BoldItalic.ttf')}}) format("truetype");
            font-weight: 700;
            font-style: italic;
        }
        * {
            font-family: 'notosans-regular, notosans-bold, notosans-bolditalic, notosans-italic';
        }
    </style>

Trong đó @font-face là nơi bạn sẽ khai báo đến font cần dùng, các thông số font-weightfont-style thì bạn dựa vào mô tả như hình dưới (được mô tả tại đây)

Đoạn code dưới đây để chỉ ra bạn sẽ sử dụng những font nào đã được khai báo bằng @font-face nếu bạn khai báo 4 font ở @font-face nhưng khi sử dụng bạn chỉ gọi 2 font là ‘notosans-regular, notosans-bold’ thì khi text của bạn là kiểu italic và có font-weight: bold thì nó sẽ bị lỗi font vì bạn chỉ gọi sử dụng 2 kiểu font là regular (normal) và bold( dành cho style normal).

* {
     font-family: 'notosans-regular, notosans-bold, notosans-bolditalic, notosans-italic';
  }
* {
     font-family: 'notosans-regular, notosans-bold, notosans-bolditalic, notosans-italic';
     font-weight: bold;
  }
* {
     font-family: 'notosans-regular, notosans-bold, notosans-bolditalic, notosans-italic';
     font-weight: bold;
     font-style: italic;
  }
* {
     font-family: 'notosans-regular, notosans-bold, notosans-bolditalic, notosans-italic';
     font-style: italic;
  }

Trong lúc sử dụng DomPDF sẽ sinh ra các file cache sau:

Đôi lúc bạn thay đổi gì đấy trong @font-face mà không thấy thay đổi gì thì có thể xóa các file này đi và chạy lại nó sẽ sinh ra các file cache mới.

** Chú ý: Nếu khi laravel bạn deploy trên hosting nếu DomPDF không nhận được font như lúc chạy dưới local thì bạn có thể chép các file cache này ở local và past vào /storage/fonts trên hosting của bạn là OK.

6. Tham khảo

https://appdividend.com/2019/09/13/laravel-6-generate-pdf-from-view-example-tutorial-from-scratch/

https://github.com/barryvdh/laravel-dompdf

https://github.com/dompdf/dompdf

Leave a Reply

Your email address will not be published. Required fields are marked *