ข้ามไปยังเนื้อหา

สร้างเอกสารหลายหน้าด้วยการขึ้นหน้าใหม่อัตโนมัติ

สร้างเอกสารหลายหน้าและเพิ่มเนื้อหาได้ต่อเนื่อง เมื่อเปิดใช้งาน setAutoPageBreak() เอนจินจัดเค้าโครงจะเริ่มหน้าใหม่เมื่อเคอร์เซอร์เลื่อนถึงระยะขอบล่าง หลังจาก save() ให้อ่านจำนวนหน้าสุดท้ายด้วย getNumPages() สูตรนี้อ้างอิง examples/05-multi-page.php เป็นหลัก

ระหว่าง save() เอนจินจะเขียนมาร์กของแต่ละหน้าลงในสตรีมเนื้อหา ISO 32000-2 §7.7.3.3 กำหนดให้ Contents ของหน้าเป็นสตรีมเดียว หรือเป็นอาร์เรย์ของสตรีมที่นำมาต่อกันตามลำดับ เอาต์พุตหลายหน้าจึงเป็นลำดับของออบเจ็กต์หน้า ไม่ใช่บัฟเฟอร์เดียว

Terminal window
composer require nextpdf/core:^3

ไม่ต้องใช้ส่วนขยายเพิ่มเติมใด ๆ สูตรนี้ทำงานได้บนเมทริกซ์ backport ของ PHP 8.1–8.4 ทั้ง getNumPages() และ setAutoPageBreak() เสถียรมาตั้งแต่ 1.0.0

เอกสาร NextPDF คือต้นไม้ของหน้า (page tree) เมื่อเพิ่มเนื้อหา เคอร์เซอร์ภายใน (getY()) จะเลื่อนลงตามหน้า เมื่อเปิดการขึ้นหน้าใหม่อัตโนมัติ เอนจินจะตรวจสอบพื้นที่แนวตั้งที่เหลืออยู่ก่อนบล็อกเนื้อหาแต่ละบล็อก หากบล็อกไม่พอดีเหนือระยะขอบล่าง เอนจินจะ flush หน้าปัจจุบันและเรียก addPage() ให้โดยอัตโนมัติ ระยะขอบล่างที่ส่งให้ setAutoPageBreak() คือเกณฑ์ที่ใช้สั่งให้ขึ้นหน้าใหม่

แอตทริบิวต์ระดับหน้า เช่น media box เป็นค่าที่สืบทอดได้ ISO 32000-2 §7.7.3.4 กำหนดว่าแอตทริบิวต์ที่ถูกละไว้จากออบเจ็กต์หน้าจะได้ค่าจากโหนดบรรพบุรุษในต้นไม้ของหน้า NextPDF กำหนดขนาดหน้าให้สอดคล้องกันทั้งเอกสาร ดังนั้นทุกหน้าที่สร้างขึ้นจึงใช้เรขาคณิตหน้าเดียวกัน และไม่ต้องกำหนดซ้ำในแต่ละหน้า

ส่วนติดต่อโปรแกรมประยุกต์ (API) สร้างจาก PHPDoc สูตรนี้ใช้เมธอดเหล่านี้:

  • Document::createStandalone(): self — สร้างเอกสารแบบแยกอิสระ
  • setAutoPageBreak(bool $enabled, float $margin = 20): static — เปิดใช้การขึ้นหน้าใหม่อัตโนมัติ $margin คือเกณฑ์ระยะขอบล่างสำหรับสั่งขึ้นหน้าใหม่ มีหน่วยเป็นมิลลิเมตร
  • addPage(?PageSize $size = null, Orientation $orientation = Orientation::Portrait): static — เริ่มหน้าแรกและหน้าใด ๆ ที่ระบุอย่างชัดเจน
  • multiCell(...): static / cell(...): static — ส่งออกบล็อกข้อความแบบไหลหรือแบบตายตัว การตรวจสอบการขึ้นหน้าใหม่จะวัดจากบล็อกเหล่านี้
  • getNumPages(): int — จำนวนหน้าหลังจากจัดเค้าโครง
<?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";

นี่คือตัวอย่างที่สมบูรณ์และพร้อมใช้กับ harness โดยใช้ค่า NEXTPDF_COOKBOOK_OUTPUT ที่ harness ตั้งไว้ ดังนั้นจึงต้องไม่ echo PDF ไปยัง STDOUT ตัวอย่างนี้ไม่เพิ่มแหล่งเอนโทรปีของตัวเอง เมื่อ harness รันตัวอย่างนี้ DeterministicMode จะตรึงนาฬิกา /ID และแบรนด์ดิ้งไว้

<?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";
  • ปิดการขึ้นหน้าใหม่อัตโนมัติ เมื่อใช้ setAutoPageBreak(false, …) เนื้อหาที่เลยระยะขอบล่างจะถูกตัด (clip) ให้อยู่ในหน้าแทนที่จะไหลต่อ และเอกสารจะยังอยู่บนหน้าเดียว เปิดใช้งานสำหรับเนื้อหาที่ต้องไหลข้ามหน้า
  • บล็อกเดียวที่สูงกว่าหน้า เอนจินจะแบ่ง multiCell ที่มีข้อความเกินความสูงที่พิมพ์ได้ให้โดยอัตโนมัติ แต่บล็อกเดียวที่แบ่งไม่ได้และสูงกว่าพื้นที่ที่ใช้ได้ เช่น รูปภาพที่สูง จะถูกวางเพียงครั้งเดียวและล้นออกนอกหน้า ควรแบ่งบล็อกนั้นเอง
  • ยังคงต้องเรียก addPage() ครั้งแรกอยู่ดี cell() จะเรียก addPage() ให้เมื่อยังไม่มีหน้าใด ถึงอย่างนั้นก็ควรเรียก addPage() อย่างชัดเจน เพื่อให้ขนาดและการวางแนวของหน้าแรกคงความ deterministic
  • หน่วยของระยะขอบ ระยะขอบของ setAutoPageBreak() มีหน่วยเป็นมิลลิเมตรในระบบหน่วยเริ่มต้น ไม่ใช่พอยต์

getNumPages() เป็น O(1) เมธอดนี้อ่านตัวนับโดยไม่จัดเค้าโครงใหม่อีกครั้ง หน่วยความจำเพิ่มขึ้นตามเนื้อหาที่เก็บไว้ ไม่ใช่ตามจำนวนหน้า เอนจินจะ flush หน้าที่เสร็จแล้วไปยังบัฟเฟอร์เอาต์พุตทันทีที่หน้านั้นเสร็จสมบูรณ์ — เป็นโมเดลสตรีมมิงแบบรอบเดียว (ADR-001) งบประมาณ 2000 ms / 64 MB ครอบคลุมเอกสารที่มีข้อความไม่กี่ร้อยหน้าบนโฮสต์อ้างอิง

สูตรนี้เขียนเฉพาะข้อความที่โค้ดกำหนดเท่านั้น ไม่มีการพาร์สอินพุต การเข้าถึงเครือข่าย หรือการดีซีเรียลไลซ์ ให้ถือว่าข้อความจากแหล่งภายนอกใด ๆ เป็นข้อมูลที่เชื่อถือไม่ได้ และกำหนดขอบเขตความยาวก่อนการเรนเดอร์ เอนจินไม่ได้กำหนดขีดจำกัดขนาดเนื้อหาในระดับแอปพลิเคชันให้โดยอัตโนมัติ

ข้อความข้อกำหนดข้อรหัสอ้างอิง (reference_id)
ส่วน Contents ของหน้าเป็นสตรีมเดียว หรืออาร์เรย์ของสตรีมที่ต่อกันตามลำดับISO 32000-2§7.7.3.3
แอตทริบิวต์หน้าที่สืบทอดได้ซึ่งถูกละไว้จากออบเจ็กต์หน้าจะได้ค่าจากโหนดบรรพบุรุษในต้นไม้ของหน้าISO 32000-2§7.7.3.4
เทรลเลอร์ /ID เป็นตัวระบุไฟล์ที่ประกอบด้วยไบต์สตริงสองตัว (จำเป็นใน PDF 2.0)ISO 32000-2§7.5.5

โปรไฟล์การทำซ้ำได้ — เชิงโครงสร้าง (เหตุใดจึงไม่ใช่ระดับบิต) เอกสารที่บันทึกทุกฉบับจะมีเทรลเลอร์ /ID ซึ่งไบต์สตริงสองตัวเป็นตัวระบุไฟล์ (ISO 32000-2 §7.5.5 ข้างต้น) ค่าที่สองไม่เสถียรระหว่างการรัน ดังนั้นไบต์ดิบจึงแตกต่างกันในแต่ละการรันแม้เนื้อหาจะเหมือนกันก็ตาม harness จะเปรียบเทียบโครงสร้างที่ผ่านการ normalize ด้วย qpdf ซึ่งตัด /ID /CreationDate และ /ModDate ออก สูตรนี้อธิบายวิธีที่ NextPDF สร้างโครงสร้างขึ้น สูตรนี้ไม่ได้ยืนยันความสอดคล้องกับ ISO 32000-2 แบบครอบคลุมทั้งหมด

ไม่เกี่ยวข้อง การจัดองค์ประกอบหลายหน้าพร้อมการขึ้นหน้าใหม่อัตโนมัติเป็นความสามารถของ Core และไม่ได้ถูกจำกัดด้วย Premium