如何在 DOMPDF 中安全传递 PHP 数据到 PDF 模板

5次阅读

如何在 DOMPDF 中安全传递 PHP 数据到 PDF 模板

本文详解如何在原生 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 解析,避免潜在的安全与执行风险。

步骤如下:

  1. 在 pdf.php 中使用清晰的占位符(如 {name}、{date});
  2. 读取模板后,用 str_replace() 替换占位符;
  3. 再传入 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>

⚠️ 注意事项:

  • 务必对 $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 DompdfDompdf::with()。请勿直接套用。

✅ 方案二(进阶):启用 isPhpEnabled 并配合 eval()(仅限可信环境)

若坚持在模板中执行 PHP(例如需循环、条件判断),必须满足两个前提:

  1. isPhpEnabled(true) 已设置;
  2. 使用 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 报告、发票、证书等业务文档。

text=ZqhQzanResources