Tạo tài liệu nhiều trang với ngắt trang tự động
Tổng quan nhanh
Phần tiêu đề “Tổng quan nhanh”Tạo một tài liệu trải dài trên nhiều trang. Thêm nội dung dần trong quá trình dựng tài liệu. Khi setAutoPageBreak() được bật, công cụ bố cục sẽ bắt đầu một trang mới khi con trỏ chạm tới lề dưới. Sau khi gọi save(), hãy đọc tổng số trang cuối cùng bằng getNumPages(). Công thức này dựa trên examples/05-multi-page.php.
Trong khi save() chạy, công cụ ghi các lệnh vẽ của từng trang vào một luồng nội dung. ISO 32000-2 §7.7.3.3 định nghĩa Contents của một trang là một luồng, hoặc là một mảng các luồng được nối theo thứ tự. Vì vậy, kết quả nhiều trang là một chuỗi các đối tượng trang, chứ không phải một bộ đệm duy nhất.
Cài đặt
Phần tiêu đề “Cài đặt”composer require nextpdf/core:^3Không cần phần mở rộng tùy chọn nào. Công thức này chạy trong ma trận backport PHP 8.1–8.4. getNumPages() và setAutoPageBreak() đều đã ổn định kể từ 1.0.0.
Tổng quan khái niệm
Phần tiêu đề “Tổng quan khái niệm”Một tài liệu NextPDF là một cây trang. Khi bạn thêm nội dung, một con trỏ nội bộ (getY()) di chuyển dần xuống dưới trang. Khi ngắt trang tự động được bật, công cụ kiểm tra khoảng trống dọc còn lại trước mỗi khối nội dung. Nếu khối đó không còn vừa trước lề dưới, công cụ sẽ đẩy trang hiện tại ra và gọi addPage() giúp bạn. Lề dưới mà bạn truyền vào setAutoPageBreak() chính là ngưỡng kích hoạt.
Các thuộc tính cấp trang, chẳng hạn như media box, có thể được kế thừa. ISO 32000-2 §7.7.3.4 quy định rằng một thuộc tính không có trong một đối tượng trang sẽ được phân giải từ một nút tổ tiên trong cây trang. NextPDF đặt kích thước trang nhất quán cho toàn bộ tài liệu, nên mọi trang được tạo ra đều dùng cùng một hình học, và bạn không phải lặp lại thuộc tính đó cho từng trang.
Bề mặt API
Phần tiêu đề “Bề mặt API”Bề mặt API được tạo ra từ PHPDoc. Công thức này dựa vào các phương thức sau:
Document::createStandalone(): self— tạo một tài liệu độc lập.setAutoPageBreak(bool $enabled, float $margin = 20): static— bật ngắt trang tự động.$marginlà ngưỡng kích hoạt lề dưới, tính bằng milimét.addPage(?PageSize $size = null, Orientation $orientation = Orientation::Portrait): static— bắt đầu trang đầu tiên, cũng như bất kỳ trang nào được thêm tường minh.multiCell(...): static/cell(...): static— xuất các khối văn bản dạng chảy tràn hoặc cố định. Cơ chế kiểm tra ngắt trang đo các khối này.getNumPages(): int— số trang sau khi bố cục.
Mẫu mã — Bắt đầu nhanh
Phần tiêu đề “Mẫu mã — Bắt đầu nhanh”<?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->setFont('helvetica', '', 11);for ($i = 1; $i <= 60; $i++) { $doc->multiCell(0, 7, "Line {$i}: content flows until the page is full, " . 'then the engine starts a new page automatically.');}
$doc->save(getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/multi-page.pdf');echo 'Pages: ' . $doc->getNumPages() . "\n";Mẫu mã — Bản chạy thực tế
Phần tiêu đề “Mẫu mã — Bản chạy thực tế”Đây là ví dụ đầy đủ, sẵn sàng cho harness. Ví dụ tôn trọng NEXTPDF_COOKBOOK_OUTPUT do harness đặt, nên không xuất tệp PDF ra STDOUT. Bản thân ví dụ không thêm bất kỳ entropy nào. Khi harness chạy, DeterministicMode ghim đồng hồ, /ID, và phần thương hiệu.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Multi-Page Document');
// Enable automatic page breaks. The 25 mm bottom margin is the trigger:// when the cursor would cross it, the engine flushes the page and adds// a new one before the next block is drawn.$doc->setAutoPageBreak(true, margin: 25);$doc->addPage();
$doc->setFont('helvetica', 'B', 18);$doc->cell(0, 12, 'Multi-Page Document Example', newLine: true);$doc->ln(5);
for ($chapter = 1; $chapter <= 3; $chapter++) { $doc->setFont('helvetica', 'B', 14); $doc->cell(0, 10, "Chapter {$chapter}: Lorem Ipsum", newLine: true); $doc->setFont('helvetica', '', 11);
for ($para = 1; $para <= 5; $para++) { $text = "Paragraph {$para} of Chapter {$chapter}. " . 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. ' . 'Sed do eiusmod tempor incididunt ut labore et dolore magna ' . 'aliqua. Ut enim ad minim veniam, quis nostrud exercitation ' . 'ullamco laboris nisi ut aliquip ex ea commodo consequat.'; $doc->multiCell(0, 7, $text); $doc->ln(3); } $doc->ln(5);}
// The harness sets NEXTPDF_COOKBOOK_OUTPUT; honour it. STDOUT stays free// for progress text only.$out = getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/multi-page.pdf';$doc->save($out);
echo 'Created multi-page.pdf with ' . $doc->getNumPages() . " pages\n";Trường hợp đặc biệt và điều cần lưu ý
Phần tiêu đề “Trường hợp đặc biệt và điều cần lưu ý”- Khi tắt ngắt trang tự động. Với
setAutoPageBreak(false, …), nội dung vượt quá lề dưới sẽ bị cắt trong phạm vi trang thay vì chảy tràn, và tài liệu vẫn nằm trên một trang duy nhất. Hãy bật tùy chọn này cho nội dung chảy tràn. - Một khối đơn cao hơn trang. Nội bộ, công cụ sẽ tách một
multiCellcó văn bản vượt quá chiều cao in được. Nhưng một khối không thể chia nhỏ và cao hơn vùng dùng được, chẳng hạn như một hình ảnh cao, sẽ được đặt một lần và tràn ra ngoài. Bạn cần tự ngắt khối đó. - Lần gọi
addPage()đầu tiên vẫn là bắt buộc.cell()gọiaddPage()khi cần nếu chưa có trang nào. Dù vậy, hãy gọiaddPage()một cách tường minh để kích thước và hướng của trang đầu tiên luôn xác định. - Đơn vị của lề. Lề của
setAutoPageBreak()được tính bằng milimét trong hệ đơn vị mặc định, chứ không phải bằng điểm.
Hiệu năng
Phần tiêu đề “Hiệu năng”getNumPages() có độ phức tạp O(1). Nó đọc một bộ đếm và không chạy lại bố cục. Mức dùng bộ nhớ tăng theo nội dung được giữ lại, chứ không theo số trang. Công cụ đẩy các trang đã hoàn tất ra bộ đệm đầu ra ngay khi hoàn tất — mô hình truyền luồng một lượt (ADR-001). Ngân sách 2000 ms / 64 MB đủ cho các tài liệu có vài trăm trang văn bản trên máy chủ tham chiếu.
Lưu ý bảo mật
Phần tiêu đề “Lưu ý bảo mật”Công thức này chỉ ghi văn bản do mã của bạn cung cấp. Nó không phân tích cú pháp đầu vào, không truy cập mạng, và không giải tuần tự hóa. Hãy coi mọi văn bản đến từ nguồn bên ngoài là không đáng tin, và áp dụng giới hạn độ dài trước khi kết xuất. Công cụ không tự áp đặt giới hạn kích thước nội dung ở cấp ứng dụng cho bạn.
Tuân thủ
Phần tiêu đề “Tuân thủ”| Phát biểu | Đặc tả | Điều khoản | reference_id |
|---|---|---|---|
Mục Contents của một trang là một luồng duy nhất hoặc một mảng các luồng được nối theo thứ tự. | ISO 32000-2 | §7.7.3.3 | |
| Thuộc tính trang có thể kế thừa; khi không có trong một đối tượng trang, thuộc tính đó sẽ được phân giải từ một nút tổ tiên trong cây trang. | ISO 32000-2 | §7.7.3.4 | |
Mục /ID trong trailer là một bộ định danh tệp gồm hai chuỗi byte (bắt buộc trong PDF 2.0). | ISO 32000-2 | §7.5.5 |
Hồ sơ khả tái lập — theo cấu trúc (vì sao không theo từng bit). Mỗi tài liệu khi được lưu đều có /ID trong trailer; hai chuỗi byte của mục này tạo thành một bộ định danh tệp (ISO 32000-2 §7.5.5, ở trên). Phần tử thứ hai không ổn định giữa các lần chạy, nên byte thô khác nhau giữa các lần chạy ngay cả với nội dung giống hệt nhau. Harness so sánh cấu trúc đã được qpdf chuẩn hóa, vốn loại bỏ /ID, /CreationDate, và /ModDate. Công thức này mô tả cách NextPDF tạo ra cấu trúc. Nó không đưa ra tuyên bố bao trùm rằng tài liệu tuân thủ ISO 32000-2.
Bối cảnh thương mại
Phần tiêu đề “Bối cảnh thương mại”Không áp dụng. Việc soạn tài liệu nhiều trang với ngắt trang tự động là một khả năng của Core, không bị giới hạn ở Premium.