tp5中生成pdf应封装为独立函数,接收数据并返回二进制流或void,避免模板调用;正确构造tcpdf实例时传尺寸数组[w,h]并指定单位,注册本地中文字体,控制器中清缓存并用response输出。

TP5里怎么写一个生成PDF的自定义函数
直接在 application/common.php 里写函数是可行的,但要注意:它只是普通 PHP 函数,不自动具备 ThinkPHP 的上下文(比如 Db、config()、模板渲染等),调用 TCPDF 时得手动引入类或确保自动加载已生效。
常见错误是把 TCPDF 实例化逻辑和业务逻辑混在一起,导致函数不可复用、难调试。正确做法是把 PDF 构造和内容填充拆开,函数只负责“接收数据 → 生成并输出/返回 PDF 字符串”。
- 函数命名建议带前缀,如
pdf_generate_receipt(),避免和框架内置函数冲突 - 不要在函数里直接
echo或exit,应返回string(PDF 二进制流)或void(仅输出),由调用方决定是否下载 - 务必检查 TCPDF 类是否已正确引入:
require_once EXTEND_PATH . 'tcpdf/tcpdf.php';或通过 Composer 自动加载
为什么 AddPage() 传尺寸不管用
因为 AddPage() 方法本身不接受页面尺寸参数——它的第三个参数(数组)只有在构造 TCPDF 实例时未指定 PAGE_FORMAT 才会生效,而 TP5 项目中多数人直接用了 'A4' 这类常量,导致后续 AddPage(['5.8', '7']) 完全被忽略。
真正起作用的是构造时传入的第三个参数,且单位必须与第二个参数('cm' / 'mm' / 'pt')严格一致。
- ✅ 正确写法:
$pdf = new TCPDF('P', 'cm', [5.8, 7], true, 'UTF-8', false); - ❌ 错误写法:
$pdf->AddPage('P', 'cm', [5.8, 7]);('cm'是非法方向参数,数组也被忽略) - ⚠️ 尺寸数组顺序是
[width, height],不是[height, width],反了会导致宽高颠倒
模板里怎么安全调用 PDF 生成函数
ThinkPHP 模板引擎不支持直接执行含副作用的操作(比如生成文件、输出二进制流),所以 {$data|pdf_generate_receipt} 这种写法极危险:一旦触发就可能破坏 HTTP 响应头,导致浏览器乱码或白屏。
真正该做的,是在控制器里完成 PDF 生成,并用 Response 显式设置 Header:
- 别在模板里调用 PDF 函数;所有 PDF 相关逻辑必须收口到控制器或服务类中
- 输出前必须清空缓冲区:
ob_end_clean();,否则前置输出(如调试echo)会让 PDF 下载失败 - 推荐返回
Response对象:return response($pdf->Output('receipt.pdf', 'S'))->header('Content-Type', 'application/pdf');
中文显示不出来?八成是字体没注册
TCPDF 默认不支持中文,即使设置了 UTF-8 编码,若未注册中文字体,文字会变成方块或空白。
最稳妥的方式是使用 addTTFfont() 注册本地 TTF 文件,而不是依赖内置的 dejavusans(它不支持中文):
- 先准备一个支持中文的 TTF 文件(如
simhei.ttf),放在public/fonts/下 - 在 PDF 函数内注册:
$pdf->addTTFfont('./public/fonts/simhei.ttf', 'TrueTypeUnicode', '', 32); - 再设置字体:
$pdf->setFont('simhei', '', 12); - ⚠️ 注意路径:TCPDF 内部用的是服务器绝对路径或相对于当前工作目录的路径,
./public/...在 CLI 和 Web 环境下行为可能不同,建议用__DIR__ . '/../../public/fonts/...'更可靠
真正麻烦的从来不是写几行代码,而是单位混淆、路径错位、字体未注册、响应头污染这四点——只要任一环节出错,PDF 就要么打不开,要么缺字,要么下不了。动手前先验证构造参数和字体路径,比反复刷新页面更省时间。











