Kiểm tra các hộp bố cục trước khi đặt nội dung
Tổng quan nhanh
Phần tiêu đề “Tổng quan nhanh”Đọc trực tiếp hình học bố cục của một tài liệu trước khi bạn đặt nội dung. Công thức này đọc hộp trang, lề, các vùng cấm ghi và con trỏ hiện tại. Nhờ đó, logic đặt nội dung của bạn có thể dùng các con số thực thay vì tọa độ phỏng đoán. Công thức này được hỗ trợ bởi examples/34-inspect-layout-boxes.php và khung kiểm thử tương ứng tests/Cookbook/Php/InspectLayoutBoxesRecipeTest.php.
Cài đặt
Phần tiêu đề “Cài đặt”composer require nextpdf/core:^3Bạn không cần gói Pro hay Enterprise. Bề mặt truy vấn bố cục là một phần của Core và chạy với PHP 8.1 đến 8.4.
Tổng quan khái niệm
Phần tiêu đề “Tổng quan khái niệm”Một trang Portable Document Format (PDF) có các hộp ranh giới. Tối thiểu, MediaBox là hình chữ nhật xác định phạm vi của trang (ISO 32000-2 §7.7.3.3). Nội dung được định vị trong không gian người dùng. Theo mặc định, không gian người dùng bắt đầu ở góc dưới bên trái và một đơn vị bằng 1/72 inch (§8.3.2). NextPDF cung cấp cho bạn góc nhìn từ trên trái thân thiện với Composer và cho phép truy cập hình học thông qua các phương thức truy vấn chỉ đọc:
getPageWidth()/getPageHeight()— kích thước hộp trang.getMargins()— đối tượng giá trịMarginhiện hành (trên/phải/dưới/trái).getPageRegions()— các vùng cấm ghi đã khai báo (PageRegion[]). Mỗi vùng là một hình chữ nhật bất biến không được đặt nội dung.getX()/getY()— con trỏ hiện tại trong không gian Composer.
Đây là các thao tác đọc lũy đẳng. Chúng không phát ra nội dung, không di chuyển con trỏ và không thay đổi trạng thái. Hãy dùng chúng để tính không gian dọc còn lại, rồi quyết định nên tiếp tục ghi hay gọi addPage(). Bạn cũng có thể đặt một khối tương đối với một vùng cấm ghi thay vì dùng độ lệch được mã hóa cứng.
Bề mặt API
Phần tiêu đề “Bề mặt API”Bề mặt API được tạo từ PHPDoc. Các điểm vào chính nằm trong các trait \NextPDF\Core\Concerns\HasPages và HasLayout:
Document::getPageWidth(): float/Document::getPageHeight(): floatDocument::getMargins(): \NextPDF\ValueObjects\MarginDocument::getPageRegions(): array(list<\NextPDF\Layout\PageRegion>)Document::addPageRegion(float $x, float $y, float $w, float $h): staticDocument::getX(): float/Document::getY(): float
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->addPage();
$pageHeight = $doc->getPageHeight();$margins = $doc->getMargins();$cursorY = $doc->getY();
// Vertical space left before the bottom margin.$remaining = $pageHeight - $margins->bottom - $cursorY;
// Geometry is in user-space units (PDF points; 1 pt = 1/72 in).echo sprintf("Page height: %.2f pt\n", $pageHeight);echo sprintf("Bottom margin: %.2f pt\n", $margins->bottom);echo sprintf("Cursor Y: %.2f pt\n", $cursorY);echo sprintf("Remaining: %.2f pt\n", $remaining);Mẫu mã — sản xuất
Phần tiêu đề “Mẫu mã — sản xuất”Chương trình độc lập này chạy trong khung kiểm thử. Nó phản chiếu examples/34-inspect-layout-boxes.php. Nó đọc hình học của trang, khai báo một vùng cấm ghi cho chân trang và đưa ra quyết định dựa trên dữ liệu cho từng khối. Nếu khối tiếp theo sẽ va chạm với một vùng hoặc vượt quá lề dưới, nó sẽ thêm một trang thay vì in đè.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Layout Box Inspection Demo');$doc->setLanguage('en');$doc->addPage();
// Read the geometry (idempotent, no side effects). Values are in// user-space units (PDF points; 1 pt = 1/72 in).$pageWidth = $doc->getPageWidth();$pageHeight = $doc->getPageHeight();$margins = $doc->getMargins();
echo sprintf("Page box: %.2f x %.2f pt\n", $pageWidth, $pageHeight);echo sprintf("Cursor start: (%.2f, %.2f)\n", $doc->getX(), $doc->getY());
// A 15 pt tall footer no-write zone across the text column.$footerHeight = 15.0;$footerTop = $pageHeight - $margins->bottom - $footerHeight;$doc->addPageRegion( $margins->left, $footerTop, $pageWidth - $margins->left - $margins->right, $footerHeight,);
$blocks = [ 'Section 1. Each block measures the live cursor against the page box ' . 'and any no-write region before it is placed.', 'Section 2. The lowest Y at which any region starts is the hard floor ' . 'for new content; crossing it forces a page break.', 'Section 3. Reading geometry is idempotent — the query methods never ' . 'advance the cursor, so they are safe in the placement loop.', 'Section 4. This final block forces a second page when the column is ' . 'already near the footer keep-out zone.',];
$blockHeight = 42.0;$pagesUsed = 1;
foreach ($blocks as $index => $text) { $cursorY = $doc->getY();
// Lowest Y a region starts at — the hard floor for new content. $regionFloor = $pageHeight - $margins->bottom; foreach ($doc->getPageRegions() as $region) { $regionFloor = min($regionFloor, $region->y); }
if ($cursorY + $blockHeight > $regionFloor) { $doc->addPage(); ++$pagesUsed; // A fresh page resets the region set; re-declare the footer zone. $footerTop = $doc->getPageHeight() - $doc->getMargins()->bottom - $footerHeight; $doc->addPageRegion( $doc->getMargins()->left, $footerTop, $doc->getPageWidth() - $doc->getMargins()->left - $doc->getMargins()->right, $footerHeight, ); }
$doc->setFont('helvetica', 'B', 12); $doc->cell(0, 8, 'Block ' . ($index + 1), newLine: true); $doc->setFont('helvetica', '', 11); $doc->multiCell(0, 7, $text); $doc->ln(6);}
// The harness sets NEXTPDF_COOKBOOK_OUTPUT and runs this script under the// semantic profile (validated by structural AST + metadata, not a byte hash).$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');$doc->save($out !== false && $out !== '' ? $out : __DIR__ . '/inspect-layout-boxes.pdf');
echo sprintf("Pages used: %d (page breaks decided from layout geometry)\n", $pagesUsed);Đây là đầu ra chuẩn (STDOUT) mong đợi. Các con số của hộp trang phản ánh kích thước trang A4 mặc định, và con trỏ bắt đầu tại điểm gốc nội dung ở phía trên bên trái:
Page box: 595.28 x 841.89 ptCursor start: (<x>, <y>)Pages used: 2 (page breaks decided from layout geometry)Trường hợp biên & điều cần lưu ý
Phần tiêu đề “Trường hợp biên & điều cần lưu ý”- Đọc trước khi trang tồn tại.
getPageWidth()vàgetPageHeight()phản ánh trang hiện tại, vì vậy hãy gọi chúng sauaddPage(). Trước khi có trang đầu tiên, chúng trả về hình học của kích thước trang mặc định, không phải một trang mà bạn chưa thêm. - Các vùng là hình chữ nhật trong không gian Composer. Một
PageRegionylà khoảng cách của Composer tính từ góc trên bên trái, nhất quán vớigetY(). Đừng nhầm nó với các tọa độ PDF thô tính từ góc dưới bên trái. - Các thao tác đọc không có tác dụng phụ. Không phương thức truy vấn nào di chuyển con trỏ hay phát ra nội dung. Việc gọi chúng trong vòng lặp dày đặc là an toàn và tốn ít chi phí.
- Lề có thể thay đổi theo từng trang. Nếu một trang sau đặt lề khác, hãy đọc lại
getMargins()thay vì lưu vào bộ nhớ đệm giá trị đầu tiên. - Các vùng không tự động dàn lại dòng văn bản. Một vùng cấm ghi là một ràng buộc mà bạn phải tuân thủ, không phải một ranh giới ngắt dòng văn bản tự động. Công thức minh họa phép kiểm tra va chạm tường minh. Đối với các thao tác ghi theo vị trí tự do, engine không bao giờ tự động di chuyển nội dung ra khỏi một vùng.
Hiệu năng
Phần tiêu đề “Hiệu năng”Mọi phương thức ở đây đều là một thao tác đọc thuộc tính. Các thao tác này chạy trong thời gian hằng số, không cấp phát bộ nhớ và không có đầu vào hay đầu ra. Ví dụ xây dựng một tài liệu nhỏ gồm nhiều trang vẫn nằm thoải mái trong ngân sách 1500 ms / 96 MB. Hồ sơ khả năng tái lập là ngữ nghĩa, vì PDF được tạo ra mang trailer /ID và siêu dữ liệu khởi tạo. Điều quan trọng nhất là các quyết định hình học có thể quan sát được của ví dụ, vì vậy khung kiểm thử xác thực các quyết định đó thông qua một abstract syntax tree (AST) có cấu trúc cùng so sánh siêu dữ liệu thay vì một byte hash.
Ghi chú bảo mật
Phần tiêu đề “Ghi chú bảo mật”- Lưu trú dữ liệu & giảm thiểu PII. Không áp dụng. Công thức đọc hình học và bố trí văn bản do bên gọi cung cấp, vì vậy nó không tạo thêm đường dữ liệu mới. Hãy áp dụng cùng nguyên tắc tối thiểu hóa cho văn bản bạn đặt như bạn vẫn làm ở bất kỳ nơi nào khác.
- Đo từ xa an toàn & làm sạch nhật ký. Ví dụ chỉ in các con số hình học và một dòng tiến trình cố định. Nó không ghi nhật ký văn bản của tài liệu.
- Mô hình mối đe dọa. Không áp dụng. Bề mặt truy vấn chỉ đọc và không phân tích bất kỳ đầu vào bên ngoài nào. Nó không phải là một ranh giới tin cậy.
- Hành vi ở chế độ FIPS. Không áp dụng. Không có thao tác mã hóa nào chạy.
Tuân thủ
Phần tiêu đề “Tuân thủ”| Tuyên bố | Đặc tả | Điều khoản | reference_id |
|---|---|---|---|
| Một đối tượng trang xác định phạm vi của nó thông qua các hộp ranh giới (MediaBox). | ISO 32000-2 | §7.7.3.3 | |
| Hình chữ nhật của trang là ranh giới nội dung. | ISO 32000-2 | §7.7.3.3 | |
| Các vị trí được đo trong không gian người dùng; một đơn vị là 1/72 inch. | ISO 32000-2 | §8.3.2 |
Công thức này đọc hình học do các điều khoản về hộp trang và không gian người dùng đã trích dẫn của ISO 32000-2 định nghĩa. Nó không khẳng định tuân thủ toàn diện ISO 32000-2. Bề mặt truy vấn bố cục dựa trên các điều khoản đã trích dẫn.