Dompdf中getCanvas()->page_text()仅首页显示,页码计数异常
问题描述
使用Dompdf生成PDF时,通过getCanvas()->page_text()方法添加页脚页码,出现以下异常:
- 首页正常显示
1/1,但后续生成的多页无页码 - 无论PDF实际页数多少,首页的
PAGE_COUNT始终固定为1 - 尝试添加Dompdf专用的
page-break-afterCSS属性,无法触发PAGE_COUNT更新
场景补充:PDF核心内容是多个带合并表头的表格,通过按行号、行高拆分表格内容为数组,在Blade模板中循环渲染实现手动分页,PDF能正常生成多页,但仅首页显示page_text生成的页码。
相关代码
PHP生成逻辑
class PdfGenerator { public static function generate($type, $resource, $is_stored = false) { $data = self::getData($type, $resource); $pdf = Pdf::loadView('pdf/' . $type, $data); $font = $pdf->getFontMetrics()->getFont("helvetica", "normal"); $canvas = $pdf->getCanvas(); $canvas->page_text(540, 785, "{PAGE_NUM} / {PAGE_COUNT}", $font, 10, array(0, 0, 0)); if ($is_stored) { $file_name = $type . ' ' . $resource->display_name; $pdf->save(storage_path('pdf').'/' . $file_name . '.pdf'); } return $pdf; } }
Blade模板结构
<html> <head> @include('pdf/partials/style') </head> <body> <header>@include('pdf/partials/table-header-invoice')</header> <footer>@include('pdf/partials/table-footer-invoice')</footer> <main> <h1>{{ucFirst(__('invoice', [], $locale))}}</h1> @include('pdf/partials/table-details-invoice') <br> {{-- 手动拆分的表格分页 --}} @foreach ($pages_array as $page) <table style="font-size: 14px"> @foreach ($page as $content_type => $contents) @include('pdf/partials/theader-' . $content_type) @include('pdf/partials/tbody-' . $content_type) <br> @endforeach </table> @endforeach </main> </body> </html>
问题原因
Dompdf的page_text()方法是在初始渲染前绑定到画布的,而手动拆分表格循环渲染的方式,会让Dompdf在首次解析HTML时无法识别内容会生成多页,导致页码变量(PAGE_NUM/PAGE_COUNT)未被正确初始化和更新,最终仅首页能渲染出初始的1/1。
解决方案
方案1:改用Dompdf自动分页(推荐)
放弃手动拆分表格的逻辑,让Dompdf自动处理分页,同时通过CSS控制表头重复:
- 给表格
<thead>添加display: table-header-group;,确保表头在每一页重复显示 - 给表格添加
page-break-inside: avoid;,避免表格被无端拆分,同时允许Dompdf自动分页 - 移除手动拆分的
$pages_array循环,直接渲染完整表格
修改后的模板核心代码:
{{-- 自动分页的表格 --}} <table style="font-size: 14px; page-break-inside: avoid;"> <thead style="display: table-header-group;"> {{-- 你的合并表头内容 --}} </thead> <tbody> {{-- 完整的表格数据 --}} </tbody> </table>
方案2:手动触发页码重新计算(保留手动分页场景)
如果必须保留手动拆分逻辑,需要先触发PDF渲染完成分页计算,再添加页码:
class PdfGenerator { public static function generate($type, $resource, $is_stored = false) { $data = self::getData($type, $resource); $pdf = Pdf::loadView('pdf/' . $type, $data); // 先渲染PDF,触发内部分页计算 $pdf->render(); // 重新获取画布并添加页码 $font = $pdf->getFontMetrics()->getFont("helvetica", "normal"); $canvas = $pdf->getCanvas(); $canvas->page_text(540, 785, "{PAGE_NUM} / {PAGE_COUNT}", $font, 10, array(0, 0, 0)); if ($is_stored) { $file_name = $type . ' ' . $resource->display_name; $pdf->save(storage_path('pdf').'/' . $file_name . '.pdf'); } return $pdf; } }
额外注意事项
- 确保使用最新版本的Dompdf,旧版本存在页码统计的已知bug
- 避免用过多
<br>标签控制间距,改用CSS的margin/padding,防止干扰分页逻辑 - 自定义header/footer的CSS设置不要影响主内容的高度计算,避免分页判断错误
内容的提问来源于stack exchange,提问作者Stroomschok
相关产品推荐
相关产品推荐

