Core / HasPages trait
At a glance
Section titled “At a glance”The HasPages concern trait manages pages. Use it to add, move, copy, and delete pages; set margins; move the cursor; and control automatic page breaks.
Install
Section titled “Install”composer require nextpdf/core:^3Conceptual overview
Section titled “Conceptual overview”trait HasPages (src/Core/Concerns/HasPages.php, since 1.2.0) is composed into Document. To add a page:
- Call
addPage(?PageSize $size = null, Orientation $orientation = Orientation::Portrait). - Optionally call
setMargins(Margin $margin)or one ofsetLeftMargin(),setTopMargin(),setRightMargin(). - Write content. The cursor resets to the top-left margin on each new page.
When you call addPage(), it flushes the current page if one is open, applies the requested size and orientation, resets the cursor to the top-left margin, and renders the configured header. The page-count cap is 10,000 pages and is fixed by an internal Document constant (private const MAX_PAGES, not part of the public API). A call past the limit throws PageLayoutException. When $size is omitted, the current page size carries forward. Orientation is applied by calling portrait() or landscape() on the size.
The coordinate model uses user units, with Y increasing downward from the page top. setX(), setY(), and setXY() move the cursor. getX(), getY(), getPageWidth(), getPageHeight(), and getMargins() read current state. setAutoPageBreak(bool $enabled, float $margin = 20) enables a break when content would overflow past the bottom-margin threshold. The next content call then adds a page automatically.
Page-collection methods — movePage(int $from, int $to), copyPage(int $index), deletePage(int $index) — reorder pages in the document. startPageGroup() begins a new page-numbering group. getGroupPageNo() returns the group-relative number. getPage() returns the zero-based current index (-1 when no page exists). getNumPages() returns the total, including the active unflushed page.
The writer emits a page tree with consistent Kids and Count values (ISO 32000-2:2020 §7.7.3). Attributes such as Resources can be inherited from an ancestor page-tree node (§7.7.3). When tagged Portable Document Format (PDF) mode is active, addPage() closes every open marked-content scope before the page break. It reopens those scopes on the new page with fresh marked-content identifiers (MCIDs), so each begin marked-content (BDC) operator has a matching end marked-content (EMC) operator on its own page (§14.6).
API surface
Section titled “API surface”| Symbol | Kind | Stability | Since |
|---|---|---|---|
addPage(?PageSize, Orientation): static | method | stable | 1.2.0 |
setMargins(Margin): static | method | stable | 1.2.0 |
setLeftMargin/setTopMargin/setRightMargin(float): static | method | stable | 1.2.0 |
setAutoPageBreak(bool, float): static | method | stable | 1.2.0 |
setX/setY/setXY(float[, float]): static | method | stable | 1.2.0 |
getX/getY/getPageWidth/getPageHeight(): float | method | stable | 1.2.0 |
getPage(): int / getNumPages(): int | method | stable | 1.2.0 |
movePage/copyPage/deletePage(int): static | method | stable | 1.2.0 |
startPageGroup(): static / getGroupPageNo(): int | method | stable | 1.2.0 |
Code sample — Quick start
Section titled “Code sample — Quick start”<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Contracts\Orientation;use NextPDF\Core\Document;use NextPDF\ValueObjects\{Margin, PageSize};
$doc = Document::createStandalone();$doc->setTitle('Page Setup Examples');$doc->setLanguage('en');
// Page 1: A4 portrait with custom margins$doc->addPage(PageSize::A4(), Orientation::Portrait);$doc->setMargins(new Margin(20.0, 15.0, 20.0, 15.0));$doc->setFont('helvetica', 'B', 16);$doc->cell(0, 12, 'Page 1: A4 Portrait', newLine: true);
// Page 2: Letter landscape$doc->addPage(PageSize::Letter(), Orientation::Landscape);$doc->setFont('helvetica', 'B', 16);$doc->cell(0, 12, 'Page 2: Letter Landscape', newLine: true);
$doc->save(__DIR__ . '/output/03-page-setup.pdf');Source: examples/03-page-setup.php.
Code sample — Production
Section titled “Code sample — Production”setAutoPageBreak() lets content flow across pages without manual page breaks.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Multi-Page Document');$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);
$doc->setFont('helvetica', '', 11);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++) { $doc->multiCell(0, 7, "Paragraph {$para} of Chapter {$chapter}. " . 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'); }}
$doc->save(__DIR__ . '/output/05-multi-page.pdf');Source: adapted from examples/05-multi-page.php.
Edge cases & gotchas
Section titled “Edge cases & gotchas”getNumPages()includes the active page that is not flushed yet; it is not the count of completed pages alone.getPage()returns-1before the firstaddPage().- Calling
addPage()past the internal10,000-page cap throwsPageLayoutException. - Y increases downward in user coordinates. The engine converts to the native PDF bottom-left origin internally. Do not pre-flip Y yourself.
- The single-margin setters rebuild the full
Marginvalue object, preserving the other three sides. There is no partial mutation. - In tagged PDF mode,
addPage()reopens active tag scopes with fresh MCIDs. Do not assume an MCID survives a page break.
Performance
Section titled “Performance”addPage() flushes one page buffer and starts another in O(page content size). The engine holds one active page plus the cursor, not a retained page list with full content (ADR-001). movePage()/copyPage()/deletePage() operate on the flushed page collection. Budget: 1500 ms / 64 MB for the canonical quick start.
Security notes
Section titled “Security notes”Page operations consume no external input other than the integer indices the caller supplies. PageManager validates out-of-range indices. This trait has no untrusted parsing path.
Conformance
Section titled “Conformance”| Claim | Source | Clause | reference_id |
|---|---|---|---|
The page tree links children through Kids arrays | ISO 32000-2:2020 | §7.7.3 | |
Count is kept consistent with the Kids array | ISO 32000-2:2020 | §7.7.3 | |
Resources may be inherited from an ancestor page-tree node | ISO 32000-2:2020 | §7.7.3 |
Clauses are paraphrased; no normative text is reproduced.
See also
Section titled “See also”/modules/core/core/document-facade/— the facade that composesHasPages/modules/core/core/— Core overview and the concern-trait model/modules/core/core/has-layout/—HasLayout: header rendered on eachaddPage()/modules/core/core/has-text-output/—HasTextOutput: the cursorcell()advances/modules/core/layout/— page-break and flow engine behindsetAutoPageBreak()/modules/core/valueobjects/—PageSize,Margin,Orientationused byaddPage()/modules/core/exception/—PageLayoutExceptionthrown past the page cap