Skip to content

事务 (TransactionManager)

事务机制让你能对文件状态创建快照,进行试探性渲染,然后再决定保留或丢弃结果。这是「尝试放入」版面逻辑的核心手段。

API 概览

方法说明返回
startTransaction()对当前文件状态创建快照static
commitTransaction()丢弃快照,保留所有变更static
rollbackTransaction()将文件还原至快照状态static

运作原理

调用 startTransaction() 时,TransactionManager 会完整复制当前文件状态 — 包含游标位置、页数、内容缓冲区与内部计数器。之后照常渲染内容。提交会丢弃快照并保留变更;回滚会用快照取代当前状态,丢弃所有已渲染的内容。

基本范例

php
use Yeeefang\TcpdfNext\Core\Document;

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

// 尝试将区块放入当前页面
$pdf->startTransaction();
$startPage = $pdf->getPage();
$pdf->multiCell(0, 6, $longText);

if ($pdf->getPage() > $startPage) {
    // 内容溢出至下一页 — 回滚后换页重新渲染
    $pdf->rollbackTransaction();
    $pdf->addPage()->multiCell(0, 6, $longText);
} else {
    $pdf->commitTransaction();
}

使用场景:尝试放入剩余空间

最常见的用途是在提交前检查内容是否放得进当前页面:

php
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()
            ->setFont('Helvetica', 'B', 14)
            ->cell(0, 8, $section['title'], newLine: true)
            ->setFont('Helvetica', '', 10)
            ->multiCell(0, 5, $section['body']);
    } else {
        $pdf->commitTransaction();
    }
}

使用场景:测量内容高度

通过事务来测量内容实际需要的垂直空间,而不真正放入文件中:

php
$pdf->startTransaction();
$startY = $pdf->getY();
$pdf->multiCell(0, 5, $text);
$height = $pdf->getY() - $startY;
$pdf->rollbackTransaction();
// 接下来就能用 $height 做版面决策

不支持嵌套事务

嵌套事务不受支持。在已有进行中的事务时再次调用 startTransaction() 会抛出异常。务必先提交或回滚后才能开始新的事务。

性能影响

事务会存储完整的文件状态快照。对于页数多、内容缓冲区大的文件,这可能导致内存用量暂时倍增。请尽量缩小事务区块 — 快照、渲染、判断,然后立即提交或回滚。

最佳实践

  • startTransaction()commitTransaction() / rollbackTransaction() 之间的代码量降到最低。
  • 确保每个 startTransaction() 都对应恰好一次 commitTransaction()rollbackTransaction()
  • 不要在事务区块内进行文件 I/O 或发送输出 — 只有文件内部的变动才能被回滚。
  • 优先测量小范围内容,而非用事务包裹整个文件生成流程。

以 LGPL-3.0-or-later 许可证发布。