Skip to content

Transactions (TransactionManager)

Transactions let you take a snapshot of the document state, render content speculatively, and then decide whether to keep or discard the result. This is the primary mechanism for "try-fit" layout logic.

API Overview

MethodDescriptionReturns
startTransaction()Take a snapshot of the current document statestatic
commitTransaction()Discard the snapshot and keep all changesstatic
rollbackTransaction()Restore the document to the snapshotstatic

All three methods return static for fluent chaining.

How It Works

When you call startTransaction(), the TransactionManager stores a full copy of the current document state — cursor position, page count, content buffers, and internal counters. You then render content as normal.

  • Commit discards the stored snapshot. The rendered content stays in the document.
  • Rollback replaces the current state with the stored snapshot. Everything rendered since startTransaction() is discarded.

Basic Example

php
use Yeeefang\TcpdfNext\Core\Document;

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

// Try to fit a block on the current page
$pdf->startTransaction();
$startPage = $pdf->getPage();
$pdf->multiCell(0, 6, $longText);

if ($pdf->getPage() > $startPage) {
    // Content overflowed to next page — rollback and try differently
    $pdf->rollbackTransaction();
    $pdf->addPage();
    $pdf->multiCell(0, 6, $longText);
} else {
    // Content fits — keep it
    $pdf->commitTransaction();
}

Use Cases

Fitting Content in a Remaining Space

The most common use case is checking whether content fits on the current page before committing it:

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();
    }
}

Measuring Content Height

Use a transaction to measure how much vertical space content will consume without actually placing it:

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

// Now use $height for layout decisions

Important Constraints

No Nesting

Nested transactions are not supported. Calling startTransaction() while a transaction is already active will throw an exception. Always commit or rollback before starting a new transaction.

Performance Impact

A transaction stores a full snapshot of the document state. For documents with many pages and large content buffers, this can temporarily double memory usage. Keep transaction blocks as small as possible — snapshot, render, decide, then commit or rollback immediately.

Best Practices

  • Keep the code between startTransaction() and commitTransaction() / rollbackTransaction() minimal.
  • Always ensure every startTransaction() is paired with exactly one commitTransaction() or rollbackTransaction().
  • Do not perform file I/O or send output within a transaction block — only document mutations can be rolled back.
  • Prefer measuring small sections rather than wrapping entire document generation in a transaction.

Released under the LGPL-3.0-or-later License.