Bỏ qua để đến nội dung

Phân trang nội dung HTML dài qua nhiều trang

Dùng ngắt trang tự động để dàn nội dung dài qua nhiều trang. Thêm mục lục để người đọc chuyển nhanh giữa các phần. Công thức này dựa trên examples/12-bookmarks-and-toc.php.

Terminal window
composer require nextpdf/core:^3

Dùng ràng buộc phiên bản này cho gói nextpdf/core. Ví dụ chạy trên PHP 8.4.

setAutoPageBreak(true, $margin) cho engine biết cần bắt đầu một trang mới trước khi nội dung vượt qua ngưỡng lề dưới. Engine tách các đoạn văn bản dài được ghi bằng multiCell() hoặc writeHtml() tại ranh giới đó. Mô-đun Cascading Style Sheets (CSS) Fragmentation (css_break_3) được xếp hạng Verified trong ma trận hỗ trợ và hỗ trợ hành vi ngắt trong pipeline Hypertext Markup Language (HTML).

bookmark($title, $level) thêm một mục lục tại vị trí hiện tại. Một mục lục Portable Document Format (PDF) được gắn với một điểm đến để người đọc nhảy trực tiếp đến một trang (ISO 32000-2). Engine ghi điểm đến đó dưới dạng mục Dest của mục lục (ISO 32000-2). Dùng tham số level để lồng các mục thành một mục lục phân cấp trong thanh bên của trình đọc.

Pipeline vẫn chạy theo chế độ một lượt (ADR-001). Engine quyết định phân trang ngay trong lúc phát luồng, mà không giữ lại cây bố cục.

  • setAutoPageBreak(bool $enabled, float $margin = 20): staticNextPDF\Core\Concerns\HasPages.
  • bookmark(string $title, int $level = 0, float $y = -1): staticNextPDF\Core\Concerns\HasNavigation.
  • multiCell(...) / writeHtml(string $html): staticNextPDF\Core\Concerns\HasTextOutput.

Bảng PHPDoc đầy đủ được sinh từ mã nguồn.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setAutoPageBreak(true, margin: 25);
$doc->addPage();
$doc->bookmark('Section 1', level: 0);
$doc->setFont('helvetica', '', 11);
for ($i = 1; $i <= 80; $i++) {
$doc->multiCell(0, 7, "Paragraph {$i} of a long flowing document.");
}
$doc->save(__DIR__ . '/out.pdf');

Ví dụ khép kín này chạy trong harness. Ví dụ dựng một tài liệu nhiều chương với mục lục lồng nhau và ngắt trang tự động, đồng thời bám sát examples/12-bookmarks-and-toc.php.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Bookmarks and Navigation');
$doc->setPrintHeader(false);
$doc->setPrintFooter(false);
$doc->setAutoPageBreak(true, margin: 25);
$chapters = [
'Chapter 1: Introduction' => ['What is NextPDF?', 'Key Features'],
'Chapter 2: Getting Started' => ['Installation', 'Your First PDF'],
'Chapter 3: Advanced Topics' => ['Worker-safe Architecture', 'Streaming Output'],
];
$body = 'NextPDF is a modern PDF 2.0 library for PHP. This paragraph is '
. 'repeated so the content overflows the page and the engine inserts '
. 'an automatic page break at the bottom-margin threshold.';
foreach ($chapters as $chapter => $sections) {
$doc->addPage();
$doc->bookmark($chapter, level: 0);
$doc->setFont('helvetica', 'B', 18);
$doc->cell(0, 12, $chapter, newLine: true);
$doc->ln(3);
foreach ($sections as $section) {
$doc->bookmark($section, level: 1);
$doc->setFont('helvetica', 'B', 14);
$doc->cell(0, 10, $section, newLine: true);
$doc->setFont('helvetica', '', 11);
for ($i = 0; $i < 12; $i++) {
$doc->multiCell(0, 7, $body);
}
$doc->ln(4);
}
}
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');
$doc->save($out !== false ? $out : __DIR__ . '/paginate-long-html.pdf');
echo "Wrote paginate-long-html.pdf\n";

Đầu ra chuẩn (STDOUT) kỳ vọng:

Wrote paginate-long-html.pdf

Trường hợp đặc biệt & điểm cần lưu ý

Phần tiêu đề “Trường hợp đặc biệt & điểm cần lưu ý”
  • Tắt rồi để quên. Khi ngắt trang tự động bị tắt, engine cắt phần nội dung vượt quá lề dưới thay vì dàn sang trang khác. Hãy bật lại trước khi có nội dung dài.
  • Nội dung không thể tách. Một khối đơn lẻ cao hơn chiều cao trang khả dụng có thể gây ra UnsplittableContentException. Một hàng bảng rất cao hoặc một ảnh lớn có thể gây ra điều này. Hãy tách nhỏ nội dung nguồn.
  • Đặt bookmark trước nội dung. Gọi bookmark() tại vị trí bạn muốn điểm đến trỏ tới. Hãy đặt nó ngay trước tiêu đề kế tiếp, trên trang mà bạn muốn.
  • Đầu trang và chân trang chiếm chỗ. Đầu trang hoặc chân trang được in làm giảm chiều cao nội dung khả dụng, và ngưỡng ngắt có tính đến điều đó. Tắt cả hai như trong ví dụ này sẽ cho bạn toàn bộ chiều cao phần thân.
  • Lồng mục lục. level là độ sâu lồng. Một mục con ở level: 1 phải đi sau một mục cha level: 0. Nếu không, trình đọc sẽ làm phẳng cây mục lục.

Engine quyết định phân trang trong một lượt phát duy nhất. Chi phí tuyến tính theo độ dài nội dung, O(n). Ngân sách là wall_ms: 2000, peak_mb: 96. Thời gian thực tế cao hơn một chút so với các công thức một trang, vì tham chiếu chéo (xref) đa trang và việc dựng mục lục cần thêm xử lý. Mô hình luồng giữ bộ nhớ trong giới hạn; mục lục vẫn chỉ là một danh sách phẳng nhỏ.

Trích đoạn ma trận hỗ trợ CSS (chỉ các hàng Verified)

Phần tiêu đề “Trích đoạn ma trận hỗ trợ CSS (chỉ các hàng Verified)”

Bảng này chỉ liệt kê lại các hàng Verified đã được kiểm chứng từ ma trận hỗ trợ CSS.

Mô-đun W3CCấp độTrạng tháiBằng chứng
CSS Fragmentation (css_break_3)3Verifiedsrc/Html/Fragmentation/, tests/Unit/Html/PagedMedia/
CSS Table (css_tables_3)3Verifiedsrc/Html/Table/ + các PDF chuẩn (golden)
CSS Cascading and Inheritance (css_cascade_3)3Verifiedsrc/Html/Cascade/

@page là các selector trang được đặt tên, thuộc về CSS Paged Media. Trước khi dựa vào chúng, hãy tra ma trận để biết hạng hiện tại của mô-đun đó.

Ràng buộc của luồng một lượt (ADR-001)

Phần tiêu đề “Ràng buộc của luồng một lượt (ADR-001)”

Engine phát ra các ngắt trang khi luồng được xử lý. Vì không giữ lại cây nào để dàn lại, mỗi quyết định ngắt là quyết định cuối cùng. Một số nội dung, chẳng hạn như tham chiếu chéo, cần biết số trang cuối cùng sau khi dàn trang. Nội dung đó bị ràng buộc bởi giới hạn này, vì vậy hãy tính đến giới hạn đó khi viết.

Phân trang thuộc về bộ điều khiển ngắt trang, không phải bộ phân tích cú pháp. Bộ phân tích cú pháp không phát ra các toán tử chuyển trang thô; nó yêu cầu ngắt trang thông qua hợp đồng của bộ điều khiển.

Mô hình luồng giữ bộ đệm trang hiện tại và danh sách mục lục phẳng, chứ không giữ tất cả các trang cùng lúc. Một tài liệu rất dài vẫn nằm trong trần giới hạn ADR-020 vì engine xả các trang đã hoàn tất. Bảng và flex container vẫn tuân theo giới hạn 5,000 nút mỗi ngữ cảnh.

Một tài liệu thù địch không thể buộc mức dùng bộ nhớ tăng không giới hạn. Các giới hạn về số phần tử và độ lồng (ADR-001), cùng với ngân sách nút theo từng ngữ cảnh (ADR-020), sẽ khống chế khối lượng xử lý. Hãy kiểm tra độ dài và cấu trúc của nội dung dài do người dùng cung cấp. Engine kết xuất tiêu đề mục lục do kẻ tấn công kiểm soát dưới dạng văn bản và không bao giờ diễn giải nội dung đó.

Phát biểuĐặc tảĐiều khoảnreference_id
Mỗi mục lục có thể được gắn với một điểm đến để người dùng nhảy trực tiếp đến nó.ISO 32000-2iso32000_2_sec12#x1.x5.p4
Mục Dest của một mục lục đặt tên điểm đến được hiển thị khi mục đó được kích hoạt.ISO 32000-2iso32000_2_sec12#x1.x11.p30

Công thức này cho thấy cách NextPDF dàn nội dung dài và dựng mục lục. Ma trận hỗ trợ xếp hạng CSS Fragmentation là Verified.

Không áp dụng.