☰
laravel-dompdf 版本演进与 3.x 升级指南:安全默认值、配置迁移与 API 变化全解析
2026/10/15 17:50:11 网站建设 项目流程
  • 后端

【免费下载链接】laravel-dompdf

A DOMPDF Wrapper for Laravel

项目地址:https://gitcode.com/gh_mirrors/la/laravel-dompdf
点击查看免费下载

laravel-dompdf 是 Laravel 官方生态中最常用的 DOMPDF 封装包,本文以其官方 CHANGELOG.md 为主线,完整梳理从 2.0 到 3.1 的关键版本节点、破坏性变更与安全默认值调整,并结合仓库内 配置文件、核心封装类、服务提供者 与 测试用例 给出源码级佐证。读完本文,你将掌握 laravel-dompdf 各版本之间的差异、从 2.x 平滑迁移到 3.x 的具体操作步骤,以及如何正确配置enable_remote、allowed_remote_hosts、artifactPathValidation与data://协议白名单,避免因版本升级引入安全风险或 PDF 渲染回归。

一、版本脉络总览:从 2.0 到 3.1 的关键节点

CHANGELOG.md 采用 Keep a Changelog 规范组织,遵循 Semantic Versioning(语义化版本)约定,所有值得记录的变更都按版本归档。截至当前仓库状态,laravel-dompdf 的版本线可以概括为下表:

版本底层 dompdf 依赖核心变化
2.0.0dompdf/dompdf 2.x移除旧 Facade 类、新增setOption、加入魔法方法、defines更名为options
2.1.xdompdf >= 2.xLaravel 11 支持、PHPUnit 转换、修复 Facade 命名参数
2.2.0dompdf >= 2.0.7修复setOptions、提升 dompdf 最低版本
3.0 / 3.0.0dompdf/dompdf 3.x收紧安全默认值、放弃 Laravel < 9 与 PHP < 8.1
3.1dompdf/dompdf 3.1.xdata://协议纳入校验规则(破坏性变更)

从版本号跃迁可以看出,2.x → 3.x 是一次以安全为导向的大版本升级:底层 DOMPDF 从 2.x 换到 3.x,同时 laravel-dompdf 主动把若干默认值从"宽松"调整为"安全优先"。后面的章节将逐项展开这些变化,并给出对应的源码与测试依据。

二、3.x 安全默认值:升级中最值得关注的变更

CHANGELOG 在 [3.0.0] 与 [3.0] 两个小节中反复强调同一个主题:3.x 改变了默认值,以提升安全性。这是 3.x 升级时最需要关注的部分,共包含三点。

1.enable_remote默认改为false

CHANGELOG 明确写道:"enable_remoteis nowfalseby default. Change with caution.(enable_remote现在默认是false,修改时务必谨慎)"。

在 config/dompdf.php 中可以看到这一默认值的落地:

/** * Enable remote file access * * If this setting is set to true, DOMPDF will access remote sites for * images and CSS files as required. * * ==== IMPORTANT ==== * This can be a security risk, ... */ 'enable_remote' => false,

配置注释里明确提示:开启后 DOMPDF 会按需访问远程站点加载图片与 CSS。如果与enable_php同时开启,并允许传入远程 HTML 内容,恶意页面中的 PHP 代码可能以服务器账户权限执行,存在被利用的风险。因此:

  • 如果你的模板中引用了 CDN 图片、远程样式表等外部资源,升级到 3.x 后需要显式将enable_remote改为true;
  • 如果只是本地资源的 PDF 渲染,请保持默认的false;
  • "Change with caution" 的告诫意味着:不要为图省事全局开启远程访问,应评估模板中所有资源的来源是否可信。

2. 新增allowedRemoteHosts与artifactPathValidation配置项

这两个配置项是 3.x 新增的,CHANGELOG 说明它们是"added the the config"(添加到配置中)。

  • allowed_remote_hosts:在 config/dompdf.php 中默认值为null。配置注释指出:数组中的每一项必须是合法主机名(hostname),用于在enable_remote开启时过滤可加载的资源;若enable_remote为false,此项不生效;保持null则允许任意远程主机。换句话说,它是远程访问的"白名单"——即使开启了enable_remote,也建议把允许访问的主机限定在可信范围内。
/** * List of allowed remote hosts * * Each value of the array must be a valid hostname. * * This will be used to filter which resources can be loaded in combination with * isRemoteEnabled. If enable_remote is FALSE, then this will have no effect. * * Leave to NULL to allow any remote host. */ 'allowed_remote_hosts' => null,
  • artifactPathValidation:在 config/dompdf.php 中默认值为null,注释说明它是"Operational artifact (log files, temporary files) path validation"(对日志文件、临时文件等运行产物的路径校验)。它用于约束 dompdf 产生的中间文件(日志、临时文件)的落盘路径,防止路径被滥用。

3. 3.1 破坏性变更:data://协议纳入校验规则

[3.1] 小节引用了 dompdf/dompdf v3.1.0 的破坏性变更说明,内容如下:

Breaking Change该版本将data://scheme 加入协议校验规则。显式定义了允许协议、但未包含data://协议的安装环境,将不再渲染>'allowed_protocols' => [ 'data://' => ['rules' => []], 'file://' => ['rules' => []], 'http://' => ['rules' => []], 'https://' => ['rules' => []], ],

但如果你此前已经执行过vendor:publish,发布到项目config/dompdf.php的配置文件中没有data://,升级到 3.1 后 base64>// 你项目中的 config/dompdf.php 需要手动补上这一行 'allowed_protocols' => [ 'data://' => ['rules' => []], // ... 其余协议 ],

仓库的 tests/PdfTest.php 中testDataImage用例即为这一行为提供了验证——它加载一个data:image/png;base64,...的 HTML 并断言能正常生成 PDF 内容(输出长度 1424 字节)。这说明当前仓库的默认配置下,data-URI 是受支持且可用的。

三、依赖与运行环境要求:PHP 8.1+、Laravel 9+、dompdf 3.x

CHANGELOG 在 3.0.0 中声明:"support for Laravel < 9 and PHP < 8.1 is dropped"(放弃对 Laravel < 9 和 PHP < 8.1 的支持)。这一点在 composer.json 中得到了硬性约束:

"require": { "php": "^8.1", "dompdf/dompdf": "^3.1", "illuminate/support": "^9|^10|^11|^12|^13" }

由此可以确定 3.x 的完整环境要求:

依赖3.x 要求2.x 时代
PHP^8.1曾支持 PHP 7.x / 8.0
Laravel(illuminate/support)^9 | ^10 | ^11 | ^12 | ^13曾支持 Laravel 6 ~ 8
dompdf/dompdf^3.12.x 依赖 dompdf 2.x(2.2.0 起最低 2.0.7)

因此升级到 3.x 的准备工作很清晰:

# 在项目根目录执行(示例),将包升级到 3.x 并同步拉取 dompdf 3.x 与字体库 composer require barryvdh/laravel-dompdf:^3.1 composer update barryvdh/laravel-dompdf dompdf/dompdf

升级前请先确认运行环境满足 PHP >= 8.1、Laravel >= 9;不满足则无法安装 3.x,只能停留在 2.x 系列。

四、配置键重命名:dompdf.defines→dompdf.options

2.0.0 将配置中的dompdf.defines更名为dompdf.options,并标注旧键名已废弃(Deprecated)。当前仓库的 ServiceProvider.php 仍保留了向后兼容逻辑:绑定dompdf.options时,会优先读取dompdf.defines,并把形如DOMPDF_XXX的键名转成小写后映射为选项:

$this->app->bind('dompdf.options', function ($app) { $defines = $app['config']->get('dompdf.defines'); if ($defines) { $options = []; foreach ($defines as $key => $value) { $key = strtolower(str_replace('DOMPDF_', '', $key)); $options[$key] = $value; } } else { $options = $app['config']->get('dompdf.options'); } if ($app['config']->get('dompdf.pdfa.enabled')) { $options['isPdfAEnabled'] = true; } return $options; });

两点值得注意:

  1. 新项目请一律使用dompdf.options数组,旧键名仅为过渡兼容而保留;
  2. 该绑定同时读取dompdf.pdfa.enabled,若为true则自动注入isPdfAEnabled选项——这是 3.x 配置中新增的 PDF/A 合规开关(详见 config/dompdf.php),与 CHANGELOG 记录的 dompdf 3.x 能力演进保持一致。

五、API 变化:setOption取代setOptions

2.0.0 引入setOption,用于"只修改指定的某一个(或某几个)选项,而不是整体替换所有选项",同时将setOptions标记为废弃。2.1.x 还修复了 Facade 场景下的命名参数传递问题,2.2.0 又修复了setOptions本身的行为(2.1.1 曾回退过一次修复)。

在 src/PDF.php 中可以看到两者的实现差异:

/** * Set/Change an option (or array of options) in Dompdf */ public function setOption($attribute, $value = null): self { $this->dompdf->getOptions()->set($attribute, $value); return $this; } /** * Replace all the Options from DomPDF */ public function setOptions(array $options, bool $mergeWithDefaults = false): self { if ($mergeWithDefaults) { $options = array_merge(app()->make('dompdf.options'), $options); } $this->dompdf->setOptions(new Options($options)); return $this; }
  • setOption:基于现有 Options 实例调用set(),只影响指定键。例如运行期动态调 DPI 与默认字体:
Pdf::setOption(['dpi' => 150, 'defaultFont' => 'sans-serif']);
  • setOptions:会用传入数组整体新建一个Options实例,覆盖全部选项;只有传mergeWithDefaults = true时才与默认配置合并。由于默认行为会丢弃其他未列出的选项,官方已建议优先使用setOption。

从 tests/PdfTest.php 的testMagicMethods用例可以看到setOption的实际效果验证——它设置temp_dir后通过$pdf->getOptions()->getTempDir()断言值为test_dir。

六、Facade 与别名的调整:统一为Facade\Pdf

2.0.0 做了两处破坏性变更:

  1. 移除了废弃的Barryvdh\DomPDF\Facade类(旧类名),改用Barryvdh\DomPDF\Facade\Pdf;
  2. 默认 Facade 由PDF改为Pdf。

在 composer.json 的extra.laravel中,两个别名都指向新 Facade:

"aliases": { "Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf", "PDF": "Barryvdh\\DomPDF\\Facade\\Pdf" }

src/Facade/Pdf.php 的__callStatic值得注意:它每次调用都通过容器make一个新的实例,而不是复用缓存实例,并且使用...$args展开参数——这正是 2.1.0 中"Fix named arguments when using facade"的源码落点,保证了命名参数(named arguments)在 Facade 静态调用下也能正确传递:

public static function __callStatic($method, $args) { $app = static::getFacadeApplication(); if (! $app) { throw new RuntimeException('Facade application has not been set.'); } // Resolve a new instance, avoid using a cached instance $instance = $app->make(static::getFacadeAccessor()); return $instance->$method(...$args); }

testAlias、testAliasCaps、testFacade三个用例分别验证了\Pdf::、\PDF::别名与Facade\Pdf::三种写法都能正常生成 PDF 并返回application/pdf响应(见 tests/PdfTest.php);testMultipleInstances则验证了每次 Facade 调用都会得到独立实例,互不干扰(tests/PdfTest.php)。

七、魔法方法:直接调用 dompdf 底层能力

2.0.0 新增"Magic methods to allow calls to Dompdf methods easier"(魔法方法,便于直接调用 Dompdf 的方法)。其实现位于 src/PDF.php 的__call:

public function __call($method, $parameters) { if (method_exists($this, $method)) { return $this->$method(...$parameters); } if (method_exists($this->dompdf, $method)) { $return = $this->dompdf->$method(...$parameters); return $return == $this->dompdf ? $this : $return; } throw new \UnexpectedValueException("Method [{$method}] does not exist on PDF instance."); }

调用链路是:优先解析封装类自身的方法;否则转发给底层的Dompdf实例;若返回的是 dompdf 实例本身,则返回$this以便继续链式调用。testMagicMethods正是依赖这一机制完成了setBaseHost('host')->setProtocol('protocol')等底层方法的链式调用与断言。对升级用户而言,这意味着 2.0 之后你可以在不修改封装类的前提下直接使用 dompdf 3.x 新增的底层 API。

八、被移除/废弃的选项:orientation与 HTML5 解析器

2.0.0 还清理了两个历史遗留:

  • orientation选项被移除:CHANGELOG 指出该选项"从未真正生效"(was never used),由options.default_paper_orientation取代。当前 config/dompdf.php 中的默认值为'portrait'。运行期仍可通过封装类提供的setPaper($size, $orientation)魔法方法临时指定方向(如Pdf::loadHTML($html)->setPaper('a4', 'landscape'))。
  • HTML5 解析器选项废弃:enable_html5_parser在 dompdf 2.x 中已"始终开启",配置项仅保留以兼容旧配置,config/dompdf.php 中标注了@deprecated This feature is now always on in dompdf 2.x。

九、升级到 3.x 的检查清单

综合 CHANGELOG 与仓库源码,把从 2.x 升级到 3.x(或 3.1)的动作用一张清单固化下来:

  1. 环境检查:确认 PHP >= 8.1、Laravel >= 9(illuminate/support ^9 ~ ^13),否则无法安装 3.x;
  2. 更新依赖:composer require barryvdh/laravel-dompdf:^3.1,让 dompdf/dompdf 同步升到 3.x;
  3. 核对已发布配置:如果执行过php artisan vendor:publish --provider="Barryvdh\DomPDF\ServiceProvider",请对比项目内config/dompdf.php与仓库默认配置,补齐新增键:
    • allowed_remote_hosts(默认null,建议按需配置白名单);
    • artifactPathValidation(默认null);
    • allowed_protocols中补上'data://' => ['rules' => []](3.1 破坏性变更);
    • 确认enable_remote按需显式设置,而不是依赖旧版隐式行为;
  4. 替换废弃 API:Facade 使用Barryvdh\DomPDF\Facade\Pdf(Pdf/PDF别名均可);动态改选项优先setOption而非setOptions;配置键使用dompdf.options而非dompdf.defines;
  5. 回归验证:用仓库 tests/PdfTest.php 覆盖的典型场景做自测——HTML/视图加载、download 与 stream 响应头、保存到磁盘或 Laravel Storage、data-URI 图片渲染、魔法方法链式调用,确保升级后无回归。

十、总结

laravel-dompdf 的 2.x → 3.x 演进,本质是一次"兼容性换安全"的大版本升级:底层 dompdf 从 2.x 升到 3.x,默认关闭远程访问、新增远程主机白名单与产物路径校验、将data://纳入协议白名单,同时明确了 PHP 8.1+ 与 Laravel 9+ 的硬性环境要求。2.0 时代积累的 API 现代化(Facade\Pdf、setOption、魔法方法、default_paper_orientation、defines→options)则构成了 2.x 用户需要同步调整的迁移面。只要对照 CHANGELOG.md、config/dompdf.php 与 composer.json 逐项核对,配合仓库测试用例做回归验证,就能平滑完成升级,既不丢功能,也不引入安全敞口。

  • 后端

【免费下载链接】laravel-dompdf

A DOMPDF Wrapper for Laravel

项目地址:https://gitcode.com/gh_mirrors/la/laravel-dompdf
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询