Skip to content

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étodoDescripciónRetorna
startTransaction()Tomar un snapshot del estado actual del documentostatic
commitTransaction()Descartar el snapshot y mantener todos los cambiosstatic
rollbackTransaction()Restaurar el documento al snapshotstatic

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

php
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:

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

Medir la altura del contenido

Usa una transacción para medir cuánto espacio vertical consumirá el contenido sin colocarlo realmente:

php
$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ño

Restricciones 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() y commitTransaction() / rollbackTransaction() al mínimo.
  • Siempre asegúrate de que cada startTransaction() esté emparejado con exactamente un commitTransaction() o rollbackTransaction().
  • 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.

Distribuido bajo la licencia LGPL-3.0-or-later.