Skip to content

Transações (TransactionManager)

Transações permitem tirar um snapshot do estado do documento, renderizar conteúdo especulativamente e então decidir se mantém ou descarta o resultado. Este é o mecanismo principal para lógica de layout "tentar-caber".

Visão Geral da API

MétodoDescriçãoRetorna
startTransaction()Tirar snapshot do estado atual do documentostatic
commitTransaction()Descartar o snapshot e manter todas as alteraçõesstatic
rollbackTransaction()Restaurar o documento para o snapshotstatic

Todos os três métodos retornam static para encadeamento fluente.

Como Funciona

Quando você chama startTransaction(), o TransactionManager armazena uma cópia completa do estado atual do documento — posição do cursor, contagem de páginas, buffers de conteúdo e contadores internos. Você então renderiza conteúdo normalmente.

  • Commit descarta o snapshot armazenado. O conteúdo renderizado permanece no documento.
  • Rollback substitui o estado atual pelo snapshot armazenado. Tudo renderizado desde startTransaction() é descartado.

Exemplo Básico

php
use Yeeefang\TcpdfNext\Core\Document;

$pdf = Document::create()
    ->addPage()
    ->setFont('Helvetica', '', 12);

// Tentar caber um bloco na página atual
$pdf->startTransaction();
$startPage = $pdf->getPage();
$pdf->multiCell(0, 6, $longText);

if ($pdf->getPage() > $startPage) {
    // Conteúdo transbordou para próxima página — rollback e tentar diferente
    $pdf->rollbackTransaction();
    $pdf->addPage();
    $pdf->multiCell(0, 6, $longText);
} else {
    // Conteúdo cabe — manter
    $pdf->commitTransaction();
}

Casos de Uso

Caber Conteúdo no Espaço Restante

O caso de uso mais comum é verificar se o conteúdo cabe na página atual antes de confirmá-lo:

php
use Yeeefang\TcpdfNext\Core\Document;

$pdf = Document::create()
    ->addPage()
    ->setFont('Helvetica', '', 10);

foreach ($sections as $section) {
    $pdf->startTransaction();
    $startPage = $pdf->getPage();

    $pdf->setFont('Helvetica', 'B', 14)
        ->cell(0, 8, $section['title'], newLine: true)
        ->setFont('Helvetica', '', 10)
        ->multiCell(0, 5, $section['body']);

    if ($pdf->getPage() > $startPage) {
        $pdf->rollbackTransaction();
        $pdf->addPage();
        $pdf->setFont('Helvetica', 'B', 14)
            ->cell(0, 8, $section['title'], newLine: true)
            ->setFont('Helvetica', '', 10)
            ->multiCell(0, 5, $section['body']);
    } else {
        $pdf->commitTransaction();
    }
}

Medindo Altura do Conteúdo

Use uma transação para medir quanto espaço vertical o conteúdo consumirá sem realmente posicioná-lo:

php
$pdf->startTransaction();
$startY = $pdf->getY();
$pdf->multiCell(0, 5, $text);
$endY = $pdf->getY();
$height = $endY - $startY;
$pdf->rollbackTransaction();

// Agora use $height para decisões de layout

Restrições Importantes

Sem Aninhamento

Transações aninhadas não são suportadas. Chamar startTransaction() enquanto uma transação já está ativa lançará uma exceção. Sempre faça commit ou rollback antes de iniciar uma nova transação.

Impacto no Desempenho

Uma transação armazena um snapshot completo do estado do documento. Para documentos com muitas páginas e grandes buffers de conteúdo, isso pode temporariamente dobrar o uso de memória. Mantenha blocos de transação o menor possível — snapshot, renderizar, decidir, então commit ou rollback imediatamente.

Melhores Práticas

  • Mantenha o código entre startTransaction() e commitTransaction() / rollbackTransaction() mínimo.
  • Sempre garanta que cada startTransaction() seja pareado com exatamente um commitTransaction() ou rollbackTransaction().
  • Não realize I/O de arquivo ou envie saída dentro de um bloco de transação — apenas mutações do documento podem sofrer rollback.
  • Prefira medir seções pequenas em vez de envolver toda a geração do documento em uma transação.

Distribuído sob a licença LGPL-3.0-or-later.