事务 (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 或发送输出 — 只有文件内部的变动才能被回滚。
- 优先测量小范围内容,而非用事务包裹整个文件生成流程。