Chào mừng các bạn đến với CodeTutHub! Trong bài viết này, chúng ta sẽ cùng nhau tìm hiểu cách tạo và xuất các tệp PDF trong ứng dụng Laravel 12 một cách dễ dàng bằng cách sử dụng thư viện Dompdf.

Việc tạo PDF từ nội dung HTML là một tính năng rất hữu ích cho nhiều ứng dụng web, từ báo cáo, hóa đơn, vé điện tử cho đến các tài liệu in ấn. Dompdf là một thư viện mã nguồn mở cho phép bạn chuyển đổi HTML và CSS thành các tệp PDF.

Hãy cùng bắt đầu nào!

1. Cài đặt Dompdf

Đầu tiên, chúng ta cần cài đặt thư viện Dompdf vào dự án Laravel của mình thông qua Composer. Mở Terminal hoặc CMD tại thư mục gốc của dự án và chạy lệnh sau:

shell
composer require barryvdh/laravel-dompdf

Sau khi cài đặt xong, bạn có thể cần publish các file cấu hình của Dompdf (đối với Laravel 12, quá trình auto-discovery đã xử lý phần lớn, nhưng việc publish file cấu hình có thể hữu ích để tùy chỉnh):

shell
php artisan vendor:publish --provider="Barryvdh\DomPDF\ServiceProvider" --tag="config"

Lệnh này sẽ tạo ra file config/dompdf.php trong dự án của bạn, nơi bạn có thể điều chỉnh các tùy chọn như cỡ giấy, hướng giấy (portrait/landscape), font chữ mặc định, v.v.

2. Tạo Controller để Xử lý PDF

Tiếp theo, chúng ta sẽ tạo một Controller để xử lý logic tạo và tải về file PDF. Hãy tạo một Controller mới bằng lệnh Artisan:

shell
php artisan make:controller PdfController

Mở file app/Http/Controllers/PdfController.php và thêm phương thức generatePdf như sau:

php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Barryvdh\DomPDF\Facade\Pdf; // Import Facade của Dompdf

class PdfController extends Controller
{
    /**
     * Generate PDF file from a view.
     *
     * @return \Illuminate\Http\Response
     */
    public function generatePdf()
    {
        // Dữ liệu mẫu để truyền vào view PDF
        $data = [
            'title' => 'CodeTutHub - Hóa Đơn Mẫu',
            'date' => date('d/m/Y'),
            'items' => [
                ['description' => 'Sản phẩm A', 'quantity' => 2, 'price' => 150000],
                ['description' => 'Sản phẩm B', 'quantity' => 1, 'price' => 250000],
                ['description' => 'Sản phẩm C', 'quantity' => 3, 'price' => 50000],
            ],
            'total' => 0,
        ];

        // Tính tổng tiền
        foreach ($data['items'] as $item) {
            $data['total'] += $item['quantity'] * $item['price'];
        }

        // Load view vào Dompdf
        $pdf = Pdf::loadView('pdf.invoice', $data); // 'pdf.invoice' là tên view của bạn

        // Tải về file PDF hoặc hiển thị trong trình duyệt
        return $pdf->download('hoa_don_codetuthub.pdf'); // Tải về với tên file đã cho
        // return $pdf->stream('hoa_don_codetuthub.pdf'); // Hiển thị trong trình duyệt
    }
}

Trong đoạn code trên:

  • Chúng ta sử dụng use Barryvdh\DomPDF\Facade\Pdf; để có thể sử dụng Facade Pdf.
  • Tạo một mảng $data chứa thông tin sẽ hiển thị trong PDF (ví dụ: hóa đơn, báo cáo).
  • Sử dụng Pdf::loadView('pdf.invoice', $data) để tải một Blade view (mà chúng ta sẽ tạo ở bước tiếp theo) và truyền dữ liệu vào đó.
  • $pdf->download('hoa_don_codetuthub.pdf') sẽ buộc trình duyệt tải về tệp PDF với tên đã cung cấp.
  • $pdf->stream('hoa_don_codetuthub.pdf') sẽ hiển thị PDF trực tiếp trong trình duyệt.

3. Tạo Blade View cho PDF

Bây giờ, chúng ta cần tạo một Blade view sẽ được chuyển đổi thành PDF. Hãy tạo một thư mục mới có tên pdf trong resources/views và một file invoice.blade.php bên trong:

plain
resources/views/pdf/invoice.blade.php

Mở file resources/views/pdf/invoice.blade.php và thêm nội dung HTML/CSS cho hóa đơn của bạn. Dompdf hỗ trợ một phần CSS 3, nhưng bạn nên giữ CSS đơn giản và inline nếu có thể để đảm bảo tương thích tốt nhất.

php
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>{{ $title }}</title>
    <style>
        body {
            font-family: 'DejaVu Sans', sans-serif; /* Hoặc font hỗ trợ tiếng Việt nếu bạn đã cấu hình */
            font-size: 14px;
            line-height: 1.6;
        }
        .container {
            width: 80%;
            margin: 0 auto;
            padding: 20px;
            border: 1px solid #eee;
            box-shadow: 0 0 10px rgba(0, 0, 0, .15);
        }
        h1, h2, h3 {
            text-align: center;
            color: #333;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
        }
        table, th, td {
            border: 1px solid #ddd;
        }
        th, td {
            padding: 8px;
            text-align: left;
        }
        th {
            background-color: #f2f2f2;
        }
        .text-right {
            text-align: right;
        }
        .total-row {
            font-weight: bold;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>{{ $title }}</h1>
        <p>Ngày: {{ $date }}</p>

        <table>
            <thead>
                <tr>
                    <th>Mô tả</th>
                    <th class="text-right">Số lượng</th>
                    <th class="text-right">Đơn giá</th>
                    <th class="text-right">Thành tiền</th>
                </tr>
            </thead>
            <tbody>
                @foreach ($items as $item)
                    <tr>
                        <td>{{ $item['description'] }}</td>
                        <td class="text-right">{{ $item['quantity'] }}</td>
                        <td class="text-right">{{ number_format($item['price'], 0, ',', '.') }} VNĐ</td>
                        <td class="text-right">{{ number_format($item['quantity'] * $item['price'], 0, ',', '.') }} VNĐ</td>
                    </tr>
                @endforeach
                <tr class="total-row">
                    <td colspan="3" class="text-right">Tổng cộng:</td>
                    <td class="text-right">{{ number_format($total, 0, ',', '.') }} VNĐ</td>
                </tr>
            </tbody>
        </table>

        <p style="margin-top: 30px;">Cảm ơn quý khách đã sử dụng dịch vụ của CodeTutHub!</p>
    </div>
</body>
</html>

Lưu ý về Font tiếng Việt: Dompdf có thể gặp vấn đề với việc hiển thị tiếng Việt nếu font mặc định không hỗ trợ. Bạn có thể cần cài đặt và sử dụng các font hỗ trợ Unicode (ví dụ: DejaVu Sans, Arial Unicode MS) và cấu hình Dompdf để sử dụng chúng. Cách dễ nhất là sử dụng 'DejaVu Sans' như trong ví dụ hoặc tìm hiểu thêm về cách cài đặt font tùy chỉnh cho Dompdf.

4. Định tuyến (Routing) cho PDF

Cuối cùng, chúng ta cần định nghĩa một route để truy cập phương thức generatePdf trong Controller. Mở file routes/web.php và thêm route sau:

php
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PdfController; // Import Controller

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

// Route để tạo và tải về PDF
Route::get('/generate-pdf', [PdfController::class, 'generatePdf'])->name('generate.pdf');

5. Chạy thử ứng dụng

Bây giờ, hãy khởi động máy chủ phát triển Laravel của bạn:

shell
php artisan serve

Mở trình duyệt và truy cập vào URL: http://127.0.0.1:8000/generate-pdf (hoặc cổng mà Laravel Artisan hiển thị). Trình duyệt của bạn sẽ tự động tải về file hoa_don_codetuthub.pdf.

Kết quả:

Kết luận

Qua bài viết này, bạn đã học được cách tạo file PDF trong Laravel 12 sử dụng thư viện Dompdf một cách đơn giản và hiệu quả. Bạn có thể tùy chỉnh nội dung PDF bằng cách chỉnh sửa Blade view và truyền bất kỳ dữ liệu nào bạn muốn.

Hy vọng hướng dẫn này hữu ích cho các dự án của bạn! Nếu có bất kỳ câu hỏi hoặc góp ý nào, đừng ngần ngại để lại bình luận bên dưới nhé.

Bạn có thể sử dụng code mẫu tại đây: https://github.com/vantoantg/laravel-12-demo/tree/origin/feature/dompdf