最省事直接用 yii2-export 扩展,底层调用 mpdf(推荐)或 dompdf,需显式配置中文字体、禁用 css 高级特性、用 table 布局、分批处理大数据量,并实测校准 mm 单位排版。

yii2-export 扩展生成 PDF 报表最省事
直接用 yii2-export(kartik-v/yii2-export)是最稳妥的选择,它底层调用 mpdf 或 dompdf,封装了 Yii2 的数据导出逻辑,不用手动拼 HTML 模板、也不用处理分页/中文字体等底层细节。
常见错误是只装扩展不配字体,导致中文显示为方块——mpdf 默认不带中文字体,必须显式注册;dompdf 则需提前加载 simhei.ttf 或 msyh.ttf 并在 CSS 中指定 font-family。
- 安装:
composer require kartik-v/yii2-export "@dev",再按文档配置ExportMenu组件 - PDF 引擎选
mpdf更推荐:渲染快、分页准、中文支持好,只需在配置里加'exportConfig' => ['pdf' => ['class' => 'kartik\export\lib\MpdfExport'] - 关键一步:复制
vendor/mpdf/mpdf/ttfonts下的中文字体文件(如simkai.ttf)到项目@app/fonts/,并在mpdf配置中指定'fontDir' => '@app/fonts'和'fontdata' => ['kai' => ['R' => 'simkai.ttf']]
自定义 PDF 模板时 HTML 必须满足 mpdf 要求
mpdf 对 HTML/CSS 支持有限,不是所有 Bootstrap 类都能用,比如 float、flex、position: fixed 会失效或错位,票据类报表常因这个导致页眉页脚偏移、表格列宽崩塌。
真实场景中,开票系统要打印带公司 LOGO、税号、明细表格、合计栏的 A4 票据,建议用纯语义化 table 布局,避免 div 嵌套,CSS 写内联或 <style></style> 标签里,并关闭响应式。
- 禁用 Bootstrap 的
container、row、col类,改用<table width="100%"> 控制宽度 <li>页眉页脚用 <code><htmlpageheader></htmlpageheader>和<htmlpagefooter></htmlpagefooter>标签(mpdf特有),别用 CSS@page伪类 - 表格边框务必写
border="1"属性或style="border: 1px solid #000;",仅靠 CSSborder-collapse不生效 - 用
ActiveDataProvider分页查数据,每次取 500 行,循环生成 HTML 片段,拼接后喂给mpdf实例 - 禁用
ExportMenu的自动导出,改用Controller中手动调$mpdf->WriteHTML($html)+$mpdf->Output('invoice.pdf', 'D') - 导出前执行
ob_end_clean()清输出缓冲,防止 header 冲突;导出后加exit,避免 Yii2 后续渲染干扰 - 设置
mpdf页面尺寸用'format' => [210, 297](A4 毫米值),别用'A4'字符串 - CSS 中避免
em、rem,全用mm或pt(1pt = 0.3528mm) - 打印前先用
$mpdf->SetDisplayMode('fullpage')强制全页显示,方便调试布局
yii2-export 导出大报表内存溢出怎么办
查 10 万行订单导出 PDF,PHP 很容易报 Fatal error: Allowed memory size of ... exhausted。这不是扩展问题,而是 mpdf 渲染前要把全部 HTML 加载进内存,再转成 PDF 流。
根本解法不是调高 memory_limit,而是分批查库 + 分页渲染。但注意:ExportMenu 默认不支持流式导出,得绕过它,手写导出逻辑。
打印票据时浏览器预览和实际 PDF 不一致
用户点“打印预览”看到的是浏览器渲染的 HTML,但最终 PDF 是 mpdf 渲染的,两者引擎不同,结果必然有差异——这是常态,不是 bug。
最常被忽略的是单位换算:cm、mm 在浏览器里按 DPI 解析,在 PDF 里按 1/72 英寸硬换算,导致 2.54cm 在 PDF 里可能差 0.1mm。票据对齐要求高,必须统一用 mm,且所有尺寸(页边距、表格高度、字体大小)都经过实测校准。
mpdf 当作一个需要反复实测的排版引擎,比当成通用 HTML 转换器更靠谱。











