You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dompdf中getCanvas()->page_text()仅首页显示,页码计数异常

问题描述

使用Dompdf生成PDF时,通过getCanvas()->page_text()方法添加页脚页码,出现以下异常:

  • 首页正常显示1/1,但后续生成的多页无页码
  • 无论PDF实际页数多少,首页的PAGE_COUNT始终固定为1
  • 尝试添加Dompdf专用的page-break-after CSS属性,无法触发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控制表头重复:

  1. 给表格<thead>添加display: table-header-group;,确保表头在每一页重复显示
  2. 给表格添加page-break-inside: avoid;,避免表格被无端拆分,同时允许Dompdf自动分页
  3. 移除手动拆分的$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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 12:10:23