Transaction (TransactionManager)
Transaction cho phép bạn chụp snapshot trạng thái document, render nội dung thử nghiệm, rồi quyết định giữ hoặc hủy kết quả. Đây là cơ chế chính cho logic layout "thử-vừa".
Tổng quan API
| Method | Mô tả | Trả về |
|---|---|---|
startTransaction() | Chụp snapshot trạng thái document hiện tại | static |
commitTransaction() | Hủy snapshot và giữ mọi thay đổi | static |
rollbackTransaction() | Khôi phục document về snapshot | static |
Cả ba method trả về static để fluent chaining.
Cách hoạt động
Khi gọi startTransaction(), TransactionManager lưu bản sao đầy đủ trạng thái document hiện tại — vị trí con trỏ, số trang, buffer nội dung và counter nội bộ. Rồi bạn render nội dung bình thường.
- Commit hủy snapshot đã lưu. Nội dung render được giữ trong document.
- Rollback thay trạng thái hiện tại bằng snapshot đã lưu. Mọi thứ render từ
startTransaction()bị hủy.
Ví dụ cơ bản
use Yeeefang\TcpdfNext\Core\Document;
$pdf = Document::create()
->addPage()
->setFont('Helvetica', '', 12);
// Thử vừa block trên trang hiện tại
$pdf->startTransaction();
$startPage = $pdf->getPage();
$pdf->multiCell(0, 6, $longText);
if ($pdf->getPage() > $startPage) {
// Nội dung tràn sang trang tiếp — rollback và thử cách khác
$pdf->rollbackTransaction();
$pdf->addPage();
$pdf->multiCell(0, 6, $longText);
} else {
// Nội dung vừa — giữ lại
$pdf->commitTransaction();
}Trường hợp sử dụng
Vừa nội dung trong khoảng trống còn lại
Trường hợp phổ biến nhất là kiểm tra nội dung có vừa trang hiện tại trước khi commit:
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();
}
}Đo chiều cao nội dung
Dùng transaction để đo nội dung tiêu thụ bao nhiêu không gian dọc mà không thực sự đặt:
$pdf->startTransaction();
$startY = $pdf->getY();
$pdf->multiCell(0, 5, $text);
$endY = $pdf->getY();
$height = $endY - $startY;
$pdf->rollbackTransaction();
// Giờ dùng $height cho quyết định layoutRàng buộc quan trọng
Không lồng nhau
Transaction lồng nhau không được hỗ trợ. Gọi startTransaction() khi transaction đang hoạt động sẽ throw exception. Luôn commit hoặc rollback trước khi bắt đầu transaction mới.
Ảnh hưởng hiệu suất
Transaction lưu snapshot đầy đủ trạng thái document. Cho tài liệu nhiều trang và buffer nội dung lớn, điều này có thể tạm thời gấp đôi bộ nhớ. Giữ block transaction nhỏ nhất có thể — snapshot, render, quyết định, rồi commit hoặc rollback ngay.
Thực hành tốt nhất
- Giữ code giữa
startTransaction()vàcommitTransaction()/rollbackTransaction()tối thiểu. - Luôn đảm bảo mỗi
startTransaction()được ghép đúng mộtcommitTransaction()hoặcrollbackTransaction(). - Không thực hiện I/O file hoặc gửi output trong block transaction — chỉ mutation document có thể rollback.
- Ưu tiên đo từng phần nhỏ thay vì bọc toàn bộ quá trình tạo document trong transaction.