friendsofcake / cakepdf
CakePHP 插件,用于创建和/或渲染 PDF,支持多种 PDF 引擎。
Requires
- php: >=8.1
- cakephp/cakephp: ^5.0.1
Requires (Dev)
- cakephp/cakephp-codesniffer: ^5.0
- dompdf/dompdf: ^2.0
- mpdf/mpdf: ^8.1.6
- phpunit/phpunit: ^10.3
- tecnickcom/tcpdf: ^6.3
Suggests
- dompdf/dompdf: If you wish to use the DomPdf engine
- mpdf/mpdf: If you wish to use the Mpdf engine
- tecnickcom/tcpdf: If you wish to use the Tcpdf engine
README
包含 CakePdf 库的插件,该库将使用 PDF 引擎将 HTML 转换为 PDF。
插件中包含的引擎
- DomPdf (^2.0)
- Mpdf (^8.0.4)
- Tcpdf (^6.3)
- WkHtmlToPdf 推荐引擎
社区维护的引擎
要求
- 以下任一渲染引擎:DomPdf、Mpdf、Tcpdf 或 wkhtmltopdf
- pdftk(可选)请参阅:http://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/
安装
使用 Composer
composer require friendsofcake/cakepdf
CakePdf 不包含任何支持的 PDF 引擎,您需要自行安装您打算使用的引擎。
推荐 wkhtmltopdf
引擎的包可以从 https://wkhtmltopdf.org/downloads.html 下载。DomPdf、Mpdf 和 Tcpdf 可以通过以下命令之一使用 composer 安装:
composer require dompdf/dompdf
composer require tecnickcom/tcpdf
composer require mpdf/mpdf
设置
使用 CakePHP 的控制台加载插件
./bin/cake plugin load CakePdf
如果您计划使用 PDF 视图功能,该功能会自动渲染并返回 PDF,以便发送到浏览器,那么您还应在您的 config/routes.php
文件中注册 pdf
扩展。
$routes->scope('/', function (\Cake\Routing\RouteBuilder $routes) { $routes->setExtensions(['pdf']); // ... });
更多设置信息可以在使用部分找到。
配置
使用 Configure::write('CakePdf', $config);
或在控制器中使用视图构建器设置名为 pdfConfig
的视图选项(仅当与 PdfView 一起使用时)。您至少需要定义 $config['engine']
。当直接使用 CakePdf 时,您也可以将配置数组传递给构造函数。引擎的值应采用 Plugin.ClassName
格式,不带引擎后缀。
配置选项
- engine: 要使用的引擎(必需),或引擎配置选项的数组
- className: 要使用的引擎类
- binary: 要使用的二进制文件(仅适用于 wkhtmltopdf)
- cwd: 当前工作目录(仅适用于 wkhtmltopdf)
- options: 引擎特定的选项。目前用于以下引擎
WkHtmlToPdfEngine
: 选项作为 CLI 参数传递TexToPdfEngine
: 选项作为 CLI 参数传递DomPdfEngine
: 选项传递给Dompdf
类的构造函数MpdfEngine
: 选项传递给Mpdf
类的构造函数
- crypto: 要使用的加密引擎,或加密配置选项的数组
- className: 要使用的加密类
- binary: 要使用的二进制文件
- pageSize: 更改默认大小,默认为 A4
- orientation: 更改默认方向,默认为纵向
- margin: 带有键:bottom、left、right、top 和其值的数组或边距
- title: 文档的标题
- delay: 在渲染 PDF 之前等待的延迟(以毫秒为单位)
- windowStatus: 在渲染 PDF 之前所需的窗口状态
- encoding: 更改编码,默认为 UTF-8
- download: 设置为 true 以强制下载,仅当使用 PdfView 时
- filename: 使用强制下载时的文档文件名
示例
Configure::write('CakePdf', [ 'engine' => 'CakePdf.WkHtmlToPdf', 'margin' => [ 'bottom' => 15, 'left' => 50, 'right' => 30, 'top' => 45, ], 'orientation' => 'landscape', 'download' => true, ]);
use CakePdf\View\Pdfiew; class InvoicesController extends AppController { // In your Invoices controller you could set additional configs, // or override the global ones: public function view($id = null) { $invoice = $this->Invoice->get($id); $this->viewBuilder()->setOption( 'pdfConfig', [ 'orientation' => 'portrait', 'filename' => 'Invoice_' . $id, ] ); $this->set('invoice', $invoice); } /** * Add Pdfiew::class to this $viewClasses property so that CakePHP automatically * switches the view class for URLs ending with `.pdf` or with appropriate `Accept` header. * * @see https://book.cakephp.com.cn/5/en/controllers.html#content-type-negotiation * @var array<string> */ public function viewClasses(): array { return $this->viewClasses[] = Pdfiew::class; } }
引擎和加密配置选项也可以是包含相关类配置选项的数组。例如:
Configure::write('CakePdf', [ 'engine' => [ 'className' => 'CakePdf.WkHtmlToPdf', // Options usable depend on the engine used. 'options' => [ 'print-media-type' => false, 'outline' => true, 'dpi' => 96, 'cover' => [ 'url' => 'cover.html', 'enable-smart-shrinking' => true, ], 'toc' => true, ], /** * For Mac OS X / Linux by default the `wkhtmltopdf` binary should * be available through environment path or you can specify location as: */ // 'binary' => '/usr/local/bin/wkhtmltopdf', /** * On Windows the engine uses the path shown below as default. * You NEED to use the path like old fashioned MS-DOS Paths, * otherwise you will get error like: * "WKHTMLTOPDF didn't return any data" */ // 'binary' => 'C:\\Progra~1\\wkhtmltopdf\\bin\\wkhtmltopdf.exe', ], ]);
用法
您可以使用 CakePdf 以两种方式使用,仔细阅读您实际需要哪种。很多人两种方式都混用,但没有得到预期结果。
1: 使用 PdfView 在浏览器中以 PDF 格式渲染(包括强制下载)
您可以为控制器操作创建 PDF 模板和布局文件,并自动渲染它们。将模板放置在 pdf
子目录中,例如 templates/Invoices/pdf/view.php
,布局将位于 templates/layout/pdf/default.php
。
然后,例如,访问 URL http://localhost/invoices/view/1.pdf
将为您提供生成的 PDF。
此外,您可以通过在路由文件中添加 Router::mapResources(['Invoices']);
来映射资源,并通过 http://localhost/invoices/1.pdf
访问相同的文档。
如果您不想在 URL 中使用 pdf
扩展名,可以省略在路由配置中注册它。然后,您可以将 Accept
请求头设置为 application/pdf
以使 CakePHP 自动切换到 PdfView
(如上所示,需要设置 viewClasses()
方法),或显式在控制器操作中切换视图类
$this->viewBuilder()->setClassName('CakePdf.Pdf');
您可以通过使用 download
选项强制 PDF 在浏览器中渲染后下载。此外,您还可以使用 filename
选项指定自定义文件名。
$this->viewBuilder()->setOption( 'pdfConfig', [ 'download' => true, // This can be omitted if "filename" is specified. 'filename' => 'Invoice_' . $id, // This can be omitted if you want a file name based on URL. ] );
2: 创建用于电子邮件附件、文件存储等的 PDF
您可以使用 CakePdf 使用视图模板创建原始 PDF 数据。视图文件路径如下所示:templates/pdf/newsletter.php
。布局文件路径如下:templates/layout/pdf/default.php
注意到两种用法类型的布局都在同一目录中,但视图模板使用不同的文件路径。您还可以将原始数据写入文件。
示例
$CakePdf = new \CakePdf\Pdf\CakePdf(); $CakePdf->template('newsletter', 'default'); $CakePdf->viewVars(['key' => 'value']); // Get the PDF string returned $pdf = $CakePdf->output(); // Or write it to file directly $pdf = $CakePdf->write(APP . 'files' . DS . 'newsletter.pdf');
加密
您可以选择使用权限加密 PDF
要使用加密,首先需要选择一个加密引擎。目前我们支持以下加密引擎
- Pdftk
用法
在您的引导文件中添加以下内容。
Configure::write('CakePdf.crypto', 'CakePdf.Pdftk');
pdfConfig 中的选项
- 保护:设置为 true 以启用加密
- 用户密码(可选):设置一个密码以打开 PDF 文件
- 所有者密码(可选):设置解锁锁定权限的密码
- 上述之一必须存在,即用户密码或所有者密码
- 权限(可选):定义权限
权限
默认情况下,我们拒绝所有权限。
要允许所有权限
将 'permission' 设置为 true
要允许特定权限
将 'permissions' 设置为一个包含以下可用权限组合的数组
- 打印
- 降级打印
- 修改
- 组装
- 复制内容
- 屏幕阅读器
- 注释
- 填写
如何做
确保 CSS、图像等在 PDF 中加载
对于 PDF 的视图模板中的静态资产,使用绝对 URL。如果您使用 HtmlHelper::image()
或 HtmlHelper::css()
,请确保已将 fullBase
选项设置为 true
。
例如
echo $this->Html->image('logo.png', ['fullBase' => true]); echo $this->Html->css('bootstrap.css', ['fullBase' => true]);
如果您无法正确获取资产 URL,您可以尝试使用文件系统路径代替资产。
<img src="<?= WWW_ROOT ?>img/logo.png" />
注意:由于 v0.12.16 的版本,wkhtmltopdf 需要选项 enable-local-file-access
才能使用本地文件系统路径作为资产。您可以通过在引擎配置数组中设置 'enable-local-file-access' => true
来启用它。
在所有页面上获取页眉和页脚
以下是一些基于 CSS 的解决方案,您可以参考以轻松获取所有 PDF 页面的页眉和页脚。