
本文详解如何在原生 DOMpdf 中将 php 变量注入 HTML 模板并正确渲染,解决 loadHTML() 无法直接访问外部变量的问题,通过字符串替换与 PHP 启用双重方案实现数据传递。
本文详解如何在原生 dompdf 中将 php 变量注入 html 模板并正确渲染,解决 `loadhtml()` 无法直接访问外部变量的问题,通过字符串替换与 php 启用双重方案实现数据传递。
DOMPDF 默认不支持 Laravel 风格的 loadView()->with() 方法,其 loadHTML() 接收的是纯字符串 HTML 内容,因此 $data 等变量在 pdf.php 中无法直接访问——即使启用了 isPhpEnabled(true),file_get_contents(“pdf.php”) 也仅读取原始文件文本,不会执行其中的 PHP 代码。所以上述代码中 将原样输出为未解析的 PHP 标签,导致 PDF 显示空白或报错。
✅ 正确方案一:使用 str_replace() 或 sprintf() 进行模板占位符替换(推荐)
这是最安全、可控且兼容性最佳的方式。不依赖 PHP 解析,避免潜在的安全与执行风险。
步骤如下:
- 在 pdf.php 中使用清晰的占位符(如 {name}、{date});
- 读取模板后,用 str_replace() 替换占位符;
- 再传入 loadHTML() 渲染。
✅ 修改后的 index.php 示例:
立即学习“PHP免费学习笔记(深入)”;
<?php require_once 'dompdf/autoload.inc.php'; use DompdfDompdf; use DompdfOptions; function runPDF() { $options = new Options(); $options->set('isPhpEnabled', false); // 显式禁用 PHP 执行(更安全) $dompdf = new Dompdf($options); $data = [ 'name' => 'John Smith', 'date' => '1/29/2015' ]; // 读取模板内容 $html = file_get_contents("pdf.php"); // 替换占位符(支持多组键值) foreach ($data as $key => $value) { $html = str_replace('{'.$key.'}', htmlspecialchars($value, ENT_QUOTES, 'UTF-8'), $html); } $dompdf->loadHTML($html); $dompdf->setPaper('A4', 'portrait'); $dompdf->render(); $dompdf->stream("niceshipest.pdf", ["Attachment" => false]); } if (isset($_GET['pdf'])) { runPDF(); } ?> <a href="?pdf=true" target="_blank">生成 PDF</a>
✅ 对应的 pdf.php(纯 HTML + 占位符):
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Value To PDF</title> <style> body { font-family: sans-serif; margin: 2cm; } h1 { color: #2c3e50; } </style> </head> <body> <h1>Hello {name}</h1> <p>Generated on: {date}</p><div class="aritcle_card flexRow"> <div class="artcardd flexRow"> <a class="aritcle_card_img" href="/xiazai/code/10684" title="传媒公司模板(RTCMS)1.0"><img src="https://img.php.cn/upload/webcode/000/000/013/176327820790052.jpg" alt="传媒公司模板(RTCMS)1.0" onError="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a href="/xiazai/code/10684" title="传媒公司模板(RTCMS)1.0">传媒公司模板(RTCMS)1.0</a> <p>传媒企业网站系统使用热腾CMS(RTCMS),根据网站板块定制的栏目,如果修改栏目,需要修改模板相应的标签。站点内容均可在后台网站基本设置中添加。全站可生成HTML,安装默认动态浏览。并可以独立设置SEO标题、关键字、描述信息。源码包中带有少量测试数据,安装时可选择演示安装或全新安装。如果全新安装,后台内容充实后,首页才能完全显示出来。(全新安装后可以删除演示数据用到的图片,目录在https://</p> </div> <a href="/xiazai/code/10684" title="传媒公司模板(RTCMS)1.0" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> </body> </html>
⚠️ 注意事项:
❌ 关于 ->with(‘key’, $value) 的常见误解
答案中提到的 $dompdf->loadHTML($html)->with(‘data’, $data) 并非 DOMPDF 原生 API。DOMPDF 的 loadHTML() 返回 Dompdf 实例,但该实例没有 with() 方法。此写法混淆了 laravel-dompdf 的扩展接口(它封装了视图渲染逻辑),在纯 DOMPDF 中会触发 Fatal error: Call to undefined method DompdfDompdf::with()。请勿直接套用。
✅ 方案二(进阶):启用 isPhpEnabled 并配合 eval()(仅限可信环境)
若坚持在模板中执行 PHP(例如需循环、条件判断),必须满足两个前提:
- isPhpEnabled(true) 已设置;
- 使用 eval(‘?>’ . $html) 动态执行 PHP 模板(⚠️ 仅限完全可信、无用户输入的场景)。
示例(不推荐用于生产):
$html = file_get_contents("pdf.php"); // 注入变量作用域后执行 ob_start(); eval('?>' . $html); $html = ob_get_clean(); $dompdf->loadHTML($html);
同时 pdf.php 需改为:
<?php /* 注意:此处不能有输出,所有 HTML 应由 echo 输出 */ ?> <!DOCTYPE html> <html> <head><meta charset="utf-8"></head> <body> <h1>Hello <?= htmlspecialchars($data['name'] ?? '', ENT_QUOTES) ?></h1> </body> </html>
⚠️ 强烈警告:eval() 存在严重安全风险,一旦 $html 含恶意代码(如来自数据库或表单),将导致远程代码执行(RCE)。生产环境严禁使用。
总结
| 方案 | 安全性 | 灵活性 | 推荐度 | 适用场景 |
|---|---|---|---|---|
| 占位符替换(str_replace) | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 所有场景,尤其含用户数据 |
| isPhpEnabled + eval() | ⭐ | ⭐⭐⭐⭐⭐ | ⭐ | 本地调试、完全静态模板 |
| 误用 ->with() | ❌(无效) | — | ❌ | 不可用,请忽略 |
始终优先选择模板字符串替换方案:它轻量、可靠、无执行风险,且与 DOMPDF 版本无关。掌握这一模式,即可高效构建动态 PDF 报告、发票、证书等业务文档。