Crie um documento de várias páginas com quebras de página automáticas
Visão geral
Seção intitulada “Visão geral”Crie um documento que se estenda por várias páginas. Adicione conteúdo à medida que avança. Quando setAutoPageBreak() está ativado, o motor de layout inicia uma nova página assim que o cursor atinge a margem inferior. Após save(), leia a contagem final de páginas com getNumPages(). Esta receita segue examples/05-multi-page.php.
Durante save(), o motor grava as marcações de cada página em um stream de conteúdo. A ISO 32000-2 §7.7.3.3 define o Contents de uma página como um único stream ou como um array de streams concatenados em ordem. Portanto, a saída de várias páginas é uma sequência de objetos de página, não um único buffer.
Instalação
Seção intitulada “Instalação”composer require nextpdf/core:^3Nenhuma extensão opcional é necessária. Esta receita é executada na matriz de backport PHP 8.1–8.4. getNumPages() e setAutoPageBreak() estão estáveis desde a 1.0.0.
Visão conceitual
Seção intitulada “Visão conceitual”Um documento NextPDF é uma árvore de páginas. À medida que você adiciona conteúdo, um cursor interno (getY()) desce pela página. Quando as quebras de página automáticas estão ativadas, o motor verifica o espaço vertical restante antes de cada bloco de conteúdo. Se o bloco não couber acima da margem inferior, o motor descarrega a página atual e chama addPage() por você. A margem inferior que você passa para setAutoPageBreak() é o limite que dispara a quebra.
Atributos no nível da página, como a media box, são herdáveis. A ISO 32000-2 §7.7.3.4 especifica que um atributo omitido de um objeto de página é resolvido a partir de um nó ancestral da árvore de páginas. O NextPDF define um tamanho de página consistente em todo o documento, para que cada página gerada use a mesma geometria e você não precise repeti-lo em cada página.
Superfície da API
Seção intitulada “Superfície da API”A superfície da API é gerada a partir do PHPDoc. Esta receita depende destes métodos:
Document::createStandalone(): self— constrói um documento isolado.setAutoPageBreak(bool $enabled, float $margin = 20): static— ativa as quebras de página automáticas.$marginé o disparo da margem inferior em milímetros.addPage(?PageSize $size = null, Orientation $orientation = Orientation::Portrait): static— inicia a primeira página e qualquer página explícita.multiCell(...): static/cell(...): static— emitem blocos de texto fluido ou fixo. A verificação de quebra de página mede esses blocos.getNumPages(): int— retorna o número de páginas após o layout.
Exemplo de código — Início rápido
Seção intitulada “Exemplo de código — Início rápido”<?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";Exemplo de código — Produção
Seção intitulada “Exemplo de código — Produção”Este é o exemplo completo, pronto para o harness. Ele respeita NEXTPDF_COOKBOOK_OUTPUT, definido pelo harness; portanto, não envie o PDF para o STDOUT. Ele não adiciona entropia própria. Quando executado pelo harness, o DeterministicMode fixa o relógio, o /ID e a marca.
<?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";Casos extremos e pegadinhas
Seção intitulada “Casos extremos e pegadinhas”- Quebra de página automática desativada. Com
setAutoPageBreak(false, …), o conteúdo que ultrapassa a margem inferior é recortado na página em vez de fluir, e o documento permanece em uma única página. Ative-a para conteúdo fluido. - Um único bloco mais alto que a página. O motor divide internamente um
multiCellcujo texto excede a altura imprimível. No entanto, um único bloco indivisível mais alto que a área utilizável, como uma imagem alta, é posicionado uma vez e transborda. Quebre-o você mesmo. - O primeiro
addPage()ainda é necessário.cell()chamaaddPage()sob demanda quando não existe nenhuma página. Mesmo assim, chameaddPage()explicitamente para que o tamanho e a orientação da primeira página permaneçam determinísticos. - Unidades de margem. A margem de
setAutoPageBreak()é expressa em milímetros no sistema de unidades padrão, não em pontos.
Desempenho
Seção intitulada “Desempenho”getNumPages() é O(1). Ele lê um contador e não executa o layout novamente. A memória escala com o conteúdo retido, não com a contagem de páginas. O motor descarrega as páginas concluídas para o buffer de saída conforme elas são finalizadas — o modelo de streaming de passagem única (ADR-001). O orçamento de 2000 ms / 64 MB cobre documentos com algumas centenas de páginas de texto no host de referência.
Notas de segurança
Seção intitulada “Notas de segurança”Esta receita grava apenas o texto que o código fornece. Ela não realiza análise de entrada, acesso à rede nem desserialização. Trate qualquer texto de origem externa como não confiável e aplique um limite de comprimento antes da renderização. O motor não impõe por você um limite de tamanho de conteúdo no nível da aplicação.
Conformidade
Seção intitulada “Conformidade”| Declaração | Especificação | Cláusula | reference_id |
|---|---|---|---|
O Contents de uma página é um único stream ou um array ordenado e concatenado de streams. | ISO 32000-2 | §7.7.3.3 | |
| Um atributo de página herdável omitido de um objeto de página é resolvido a partir de um nó ancestral da árvore de páginas. | ISO 32000-2 | §7.7.3.4 | |
O /ID do trailer é um identificador de arquivo de duas byte-strings (obrigatório no PDF 2.0). | ISO 32000-2 | §7.5.5 |
Perfil de reprodutibilidade — estrutural (por que não bit a bit). Todo documento salvo carrega um /ID no trailer cujas duas byte-strings são um identificador de arquivo (ISO 32000-2 §7.5.5, acima). O segundo elemento não é estável entre execuções, portanto os bytes brutos diferem entre execuções mesmo para conteúdo idêntico. O harness compara a estrutura normalizada pelo qpdf, que remove /ID, /CreationDate e /ModDate. Esta receita descreve como o NextPDF produz a estrutura. Ela não afirma a conformidade com a ISO 32000-2 como uma alegação genérica.
Contexto comercial
Seção intitulada “Contexto comercial”Não se aplica. A composição de várias páginas com quebras de página automáticas é um recurso do Core, sem restrição Premium.