สร้างเอกสารหลายหน้าด้วยการขึ้นหน้าใหม่อัตโนมัติ
ภาพรวมโดยย่อ
หัวข้อที่มีชื่อว่า “ภาพรวมโดยย่อ”สร้างเอกสารหลายหน้าและเพิ่มเนื้อหาได้ต่อเนื่อง เมื่อเปิดใช้งาน setAutoPageBreak() เอนจินจัดเค้าโครงจะเริ่มหน้าใหม่เมื่อเคอร์เซอร์เลื่อนถึงระยะขอบล่าง หลังจาก save() ให้อ่านจำนวนหน้าสุดท้ายด้วย getNumPages() สูตรนี้อ้างอิง examples/05-multi-page.php เป็นหลัก
ระหว่าง save() เอนจินจะเขียนมาร์กของแต่ละหน้าลงในสตรีมเนื้อหา ISO 32000-2 §7.7.3.3 กำหนดให้ Contents ของหน้าเป็นสตรีมเดียว หรือเป็นอาร์เรย์ของสตรีมที่นำมาต่อกันตามลำดับ เอาต์พุตหลายหน้าจึงเป็นลำดับของออบเจ็กต์หน้า ไม่ใช่บัฟเฟอร์เดียว
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”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
หัวข้อที่มีชื่อว่า “ส่วนติดต่อ API”ส่วนติดต่อโปรแกรมประยุกต์ (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