
本文详解如何在原生 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 Dompdf\Dompdf;
use Dompdf\Options;
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>⚠️ 注意事项:
- 务必对 $value 调用 htmlspecialchars(),防止 XSS(尤其当数据来自用户输入时);
- 占位符命名建议统一用大括号包裹(如 {name}),避免与 HTML 属性或 CSS 冲突;
- 若模板复杂,可封装为 renderTemplate($html, $data) 辅助函数提升复用性。
❌ 关于 ->with('key', $value) 的常见误解
答案中提到的 $dompdf->loadHTML($html)->with('data', $data) 并非 DOMPDF 原生 API。DOMPDF 的 loadHTML() 返回 Dompdf 实例,但该实例没有 with() 方法。此写法混淆了 Laravel-dompdf 的扩展接口(它封装了视图渲染逻辑),在纯 DOMPDF 中会触发 Fatal error: Call to undefined method Dompdf\Dompdf::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 报告、发票、证书等业务文档。










