Transacciones (TransactionManager)
Las transacciones te permiten tomar un snapshot del estado del documento, renderizar contenido de forma especulativa y luego decidir si mantener o descartar el resultado. Este es el mecanismo principal para la lógica de diseño "probar si cabe".
Resumen de la API
| Método | Descripción | Retorna |
|---|---|---|
startTransaction() | Tomar un snapshot del estado actual del documento | static |
commitTransaction() | Descartar el snapshot y mantener todos los cambios | static |
rollbackTransaction() | Restaurar el documento al snapshot | static |
Los tres métodos retornan static para encadenamiento fluido.
Cómo funciona
Cuando llamas a startTransaction(), el TransactionManager almacena una copia completa del estado actual del documento — posición del cursor, conteo de páginas, buffers de contenido y contadores internos. Luego renderizas contenido normalmente.
- Commit descarta el snapshot almacenado. El contenido renderizado permanece en el documento.
- Rollback reemplaza el estado actual con el snapshot almacenado. Todo lo renderizado desde
startTransaction()se descarta.
Ejemplo básico
use Yeeefang\TcpdfNext\Core\Document;
$pdf = Document::create()
->addPage()
->setFont('Helvetica', '', 12);
// Intentar ajustar un bloque en la página actual
$pdf->startTransaction();
$startPage = $pdf->getPage();
$pdf->multiCell(0, 6, $longText);
if ($pdf->getPage() > $startPage) {
// El contenido desbordó a la siguiente página — rollback e intentar diferente
$pdf->rollbackTransaction();
$pdf->addPage();
$pdf->multiCell(0, 6, $longText);
} else {
// El contenido cabe — mantenerlo
$pdf->commitTransaction();
}Casos de uso
Ajustar contenido en el espacio restante
El caso de uso más común es verificar si el contenido cabe en la página actual antes de confirmarlo:
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();
}
}Medir la altura del contenido
Usa una transacción para medir cuánto espacio vertical consumirá el contenido sin colocarlo realmente:
$pdf->startTransaction();
$startY = $pdf->getY();
$pdf->multiCell(0, 5, $text);
$endY = $pdf->getY();
$height = $endY - $startY;
$pdf->rollbackTransaction();
// Ahora usa $height para decisiones de diseñoRestricciones importantes
Sin anidación
Las transacciones anidadas no están soportadas. Llamar a startTransaction() mientras una transacción ya está activa lanzará una excepción. Siempre confirma o deshaz antes de iniciar una nueva transacción.
Impacto en el rendimiento
Una transacción almacena un snapshot completo del estado del documento. Para documentos con muchas páginas y buffers de contenido grandes, esto puede duplicar temporalmente el uso de memoria. Mantén los bloques de transacción lo más pequeños posible — snapshot, renderizar, decidir, luego confirmar o deshacer inmediatamente.
Mejores prácticas
- Mantén el código entre
startTransaction()ycommitTransaction()/rollbackTransaction()al mínimo. - Siempre asegúrate de que cada
startTransaction()esté emparejado con exactamente uncommitTransaction()orollbackTransaction(). - No realices E/S de archivos ni envíes salida dentro de un bloque de transacción — solo las mutaciones del documento pueden deshacerse.
- Prefiere medir secciones pequeñas en lugar de envolver la generación completa del documento en una transacción.