Tworzenie dokumentu wielostronicowego z automatycznymi podziałami stron
W skrócie
Dział zatytułowany „W skrócie”Utwórz dokument obejmujący wiele stron. Dodawaj treść sukcesywnie. Po włączeniu setAutoPageBreak() silnik układu rozpoczyna nową stronę, gdy kursor osiągnie dolny margines. Po wywołaniu save() odczytaj ostateczną liczbę stron za pomocą getNumPages(). Ten przepis opiera się na examples/05-multi-page.php.
W trakcie wywołania save() silnik zapisuje znaczniki każdej strony w strumieniu treści. ISO 32000-2 §7.7.3.3 definiuje element Contents strony jako jeden strumień albo tablicę strumieni połączonych w kolejności. Wynik wielostronicowy jest więc sekwencją obiektów stron, a nie pojedynczym buforem.
Instalacja
Dział zatytułowany „Instalacja”composer require nextpdf/core:^3Nie jest wymagane żadne opcjonalne rozszerzenie. Ten przepis działa w ramach macierzy backportów PHP 8.1–8.4. Metody getNumPages() oraz setAutoPageBreak() są stabilne od wersji 1.0.0.
Przegląd koncepcyjny
Dział zatytułowany „Przegląd koncepcyjny”Dokument NextPDF ma postać drzewa stron. W miarę dodawania treści wewnętrzny kursor (getY()) przesuwa się w dół strony. Po włączeniu automatycznych podziałów stron silnik sprawdza pozostałe miejsce w pionie przed każdym blokiem treści. Jeśli blok nie zmieści się nad dolnym marginesem, silnik finalizuje bieżącą stronę i automatycznie wywołuje addPage(). Dolny margines przekazany do setAutoPageBreak() jest progiem wyzwalającym.
Atrybuty poziomu strony, takie jak media box, są dziedziczone. ISO 32000-2 §7.7.3.4 określa, że atrybut pominięty w obiekcie strony jest rozwiązywany na podstawie nadrzędnego węzła drzewa stron. NextPDF ustawia jeden spójny rozmiar strony w całym dokumencie, więc każda wygenerowana strona korzysta z tej samej geometrii i nie trzeba powtarzać tej konfiguracji dla każdej strony.
Powierzchnia API
Dział zatytułowany „Powierzchnia API”Powierzchnia API jest generowana z PHPDoc. Ten przepis korzysta z następujących metod:
Document::createStandalone(): self— tworzy samodzielny dokument.setAutoPageBreak(bool $enabled, float $margin = 20): static— włącza automatyczne podziały stron.$marginto próg dolnego marginesu wyrażony w milimetrach.addPage(?PageSize $size = null, Orientation $orientation = Orientation::Portrait): static— rozpoczyna pierwszą stronę oraz każdą stronę dodaną jawnie.multiCell(...): static/cell(...): static— generują przepływające albo stałe bloki tekstu. Mechanizm kontroli podziału strony mierzy właśnie te bloki.getNumPages(): int— liczba stron po wykonaniu układu.
Przykład kodu — szybki start
Dział zatytułowany „Przykład kodu — szybki start”<?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";Przykład kodu — produkcja
Dział zatytułowany „Przykład kodu — produkcja”To kompletny przykład, gotowy do uruchomienia w środowisku testowym. Uwzględnia zmienną NEXTPDF_COOKBOOK_OUTPUT, ustawianą przez środowisko testowe, dlatego nie wypisuje pliku PDF do STDOUT. Nie dodaje własnej entropii. Po uruchomieniu przez środowisko testowe tryb DeterministicMode ustala stały zegar, /ID oraz elementy marki.
<?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";Przypadki brzegowe i pułapki
Dział zatytułowany „Przypadki brzegowe i pułapki”- Wyłączony automatyczny podział strony. Przy
setAutoPageBreak(false, …)treść wykraczająca poza dolny margines jest przycinana na stronie zamiast przechodzić na następną, a dokument pozostaje jednostronicowy. Włącz automatyczny podział dla płynącej treści. - Pojedynczy blok wyższy niż strona. Silnik wewnętrznie dzieli tekst w
multiCell, jeśli tekst przekracza wysokość obszaru drukowania. Jednak pojedynczy, niepodzielny blok wyższy niż obszar użytkowy, na przykład wysoki obraz, jest umieszczany raz i wychodzi poza stronę. Podziel taki blok samodzielnie. - Pierwsze wywołanie
addPage()nadal jest wymagane.cell()wywołujeaddPage()na żądanie, jeśli nie ma jeszcze żadnej strony. Mimo to wywołujaddPage()jawnie, aby rozmiar i orientacja pierwszej strony pozostały deterministyczne. - Jednostki marginesu. Margines w
setAutoPageBreak()jest wyrażony w milimetrach w domyślnym systemie jednostek, a nie w punktach.
Wydajność
Dział zatytułowany „Wydajność”getNumPages() ma złożoność O(1). Odczytuje licznik i nie uruchamia układu ponownie. Zużycie pamięci skaluje się wraz z przechowywaną treścią, a nie z liczbą stron. Silnik przekazuje ukończone strony do bufora wyjściowego w miarę ich finalizowania – to model strumieniowania jednoprzebiegowego (ADR-001). Budżet 2000 ms / 64 MB obejmuje dokumenty z kilkuset stronami tekstu na hoście referencyjnym.
Uwagi dotyczące bezpieczeństwa
Dział zatytułowany „Uwagi dotyczące bezpieczeństwa”Ten przepis zapisuje wyłącznie tekst dostarczony przez kod aplikacji. Nie wykonuje żadnego parsowania danych wejściowych, nie korzysta z sieci ani nie przeprowadza deserializacji. Każdy tekst pochodzący z zewnętrznego źródła traktuj jako niezaufany i przed renderowaniem nałóż limit długości. Silnik nie narzuca limitu rozmiaru treści na poziomie aplikacji.
Zgodność
Dział zatytułowany „Zgodność”| Stwierdzenie | Specyfikacja | Klauzula | reference_id |
|---|---|---|---|
Element Contents strony to pojedynczy strumień albo uporządkowana tablica strumieni łączonych w kolejności. | ISO 32000-2 | §7.7.3.3 | |
| Jeżeli dziedziczony atrybut strony pominięto w obiekcie strony, jest on rozwiązywany na podstawie nadrzędnego węzła drzewa stron. | ISO 32000-2 | §7.7.3.4 | |
Element /ID w zwiastunie to identyfikator pliku złożony z dwóch ciągów bajtów (wymagany w PDF 2.0). | ISO 32000-2 | §7.5.5 |
Profil odtwarzalności — strukturalny (dlaczego nie bitowy). Każdy zapisany dokument zawiera w zwiastunie element /ID, którego dwa ciągi bajtów stanowią identyfikator pliku (ISO 32000-2 §7.5.5, powyżej). Drugi ciąg nie jest stabilny między uruchomieniami, więc surowe bajty różnią się między kolejnymi uruchomieniami nawet przy identycznej treści. Środowisko testowe porównuje strukturę znormalizowaną przez narzędzie qpdf, które usuwa elementy /ID, /CreationDate oraz /ModDate. Ten przepis opisuje, jak NextPDF tworzy tę strukturę. Nie jest to ogólne zapewnienie o zgodności z ISO 32000-2.
Kontekst komercyjny
Dział zatytułowany „Kontekst komercyjny”Nie dotyczy. Komponowanie dokumentów wielostronicowych z automatycznymi podziałami stron jest funkcją Core i nie jest objęte bramką Premium.