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étodo | Descrição | Retorna |
|---|---|---|
startTransaction() | Tirar snapshot do estado atual do documento | static |
commitTransaction() | Descartar o snapshot e manter todas as alterações | static |
rollbackTransaction() | Restaurar o documento para o snapshot | static |
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
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:
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:
$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 layoutRestriçõ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()ecommitTransaction()/rollbackTransaction()mínimo. - Sempre garanta que cada
startTransaction()seja pareado com exatamente umcommitTransaction()ourollbackTransaction(). - 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.