renatio / dynamicpdf-plugin
October HTML到PDF转换器,使用dompdf库。
Requires
- barryvdh/laravel-dompdf: ^2.0
- composer/installers: ~1.0
- october/rain: ^3.0
README
演示URL: https://october-demo.renatio.com/backend/backend/auth/signin
登录: dynamicpdf
密码: dynamicpdf
此插件允许开发人员通过简单的用户界面创建和编辑PDF模板。
HTML到PDF转换器使用dompdf库。
插件使用Laravel的dompdf包装barryvdh/laravel-dompdf。
喜欢这个插件吗?
如果你喜欢这个插件,请给它点赞或通过PayPal捐款。
我的其他插件
请查看我的其他插件。
支持
请使用GitHub问题页面报告插件中的任何问题。
评论不应用于获取支持或报告错误,如需支持,请使用插件支持链接。
图标由Darius Dan来自www.flaticon.com制作。
文档
安装
安装此插件有多种方式。
- 使用
php artisan plugin:install Renatio.DynamicPDF
命令。 - 在项目根目录中使用
composer require renatio/dynamicpdf-plugin
。当你使用此选项时,必须在安装后运行php artisan october:migrate
。
PDF内容
在October中,可以使用PDF视图或PDF模板创建PDF。PDF视图由插件提供,位于文件系统中的/views目录。而PDF模板则通过后端界面在设置 > PDF > PDF模板中进行管理。所有PDF模板都支持使用Twig进行标记。
PDF视图必须通过插件注册文件中的registerPDFTemplates
和registerPDFLayouts
方法进行注册。这将自动生成PDF模板和布局,并允许通过后端界面进行自定义。
PDF布局视图
PDF布局视图位于文件系统中,使用的代码代表视图文件的路径。例如,代码为author.plugin::pdf.layouts.default的PDF布局将使用以下文件中的内容
plugins/ <=== Plugins directory
author/ <=== "author" segment
plugin/ <=== "plugin" segment
views/ <=== View directory
pdf/ <=== "pdf" segment
layouts/ <=== "layouts" segment
default.htm <=== "default" segment
PDF视图文件内的内容可以包括最多3个部分: 配置、CSS/LESS和HTML标记。部分由==
序列分隔。例如
name = "Default PDF layout"
==
body {
font-size: 16px;
}
==
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Document</title>
<style type="text/css" media="screen">
{{ css|raw }}
</style>
</head>
<body>
{{ content_html|raw }}
</body>
</html>
注意:PDF视图中支持基本Twig标签和表达式。
CSS/LESS部分是可选的,视图可以只包含配置和HTML标记部分。
name = "Default PDF layout"
==
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Document</title>
<style type="text/css" media="screen">
{{ css|raw }}
</style>
</head>
<body>
{{ content_html|raw }}
</body>
</html>
配置部分
配置部分设置PDF视图参数。以下配置参数受支持
使用PDF布局
PDF布局存储在数据库中,可以通过选择设置 > PDF > PDF模板并点击*布局*选项卡来创建。它们的行为就像CMS布局一样,包含PDF的框架。PDF视图和模板支持使用PDF布局。布局中指定的代码是唯一的标识符,一旦创建就不能更改。
PDF模板视图
PDF模板存储在文件系统中,使用的代码表示视图文件的路径。例如,代码为author.plugin::pdf.invoice的PDF模板将使用以下文件的内容:
plugins/ <=== Plugins directory
author/ <=== "author" segment
plugin/ <=== "plugin" segment
views/ <=== View directory
pdf/ <=== "pdf" segment
invoice.htm <=== "invoice" segment
PDF视图文件内的内容可以包括最多2个部分:配置和HTML标记。部分由==
序列分隔。例如:
title = "Invoice"
layout = "renatio.demo::pdf.layouts.default"
description = "Invoice template"
size = "a4"
orientation = "portrait"
==
<h1>Invoice</h1>
注意:PDF视图中支持基本Twig标签和表达式。
配置部分
配置部分设置PDF视图参数。以下配置参数受支持
使用PDF模板
PDF模板存储在数据库中,可以通过设置 > PDF > PDF模板在后台区域创建。模板中指定的代码是唯一的标识符,一旦创建就不能更改。
注意:如果系统中不存在PDF模板,此代码将尝试查找具有相同代码的PDF视图。
注册PDF模板和布局
PDF视图可以作为模板注册,这些模板将在后台自动生成,以便进行自定义。可以通过设置 > PDF模板菜单自定义PDF模板。可以通过添加插件注册类(Plugin.php
)的registerPDFTemplates
方法来注册模板。
public function registerPDFTemplates()
{
return [
'renatio.demo::pdf.invoice',
'renatio.demo::pdf.resume',
];
}
该方法应返回一个包含PDF视图名称的数组。
就像模板一样,PDF布局也可以通过添加插件注册类(Plugin.php
)的registerPDFLayouts
方法来注册。
public function registerPDFLayouts()
{
return [
'renatio.demo::pdf.layouts.invoice',
'renatio.demo::pdf.layouts.resume',
];
}
该方法应返回一个包含PDF视图名称的数组。
用法
可以通过设置 > PDF > PDF模板在后台区域访问PDF模板和布局。
布局定义了PDF框架,即PDF上重复出现的一切,例如页眉和页脚。每个布局都有唯一的代码、可选的背景图像、HTML内容和CSS/LESS内容。并非所有CSS属性都受支持,因此请检查CSS兼容性。
模板定义了从HTML解析的实际PDF内容。
配置
默认配置设置在config/dompdf.php
中。将此文件复制到您的自己的配置目录以修改值。您可以使用以下命令发布配置:
php artisan vendor:publish --provider="Barryvdh\DomPDF\ServiceProvider"
您仍然可以在生成PDF之前使用动态方法更改dompdf选项,例如:
PDF::loadTemplate('renatio::invoice')
->setDpi(300)
->setDefaultFont('sans-serif')
->stream();
或者您可以在使用以下命令生成PDF之前使用setOption
方法:
PDF::loadTemplate('renatio::invoice')
->setOption(['dpi' => 300, 'defaultFont' => 'sans-serif'])
->stream();
可用选项及其默认值
- rootDir: "{app_directory}/vendor/dompdf/dompdf"
- tempDir: "/tmp" (在config/dompdf.php中可用)
- fontDir: "{app_directory}/storage/fonts/" (在config/dompdf.php中可用)
- fontCache: "{app_directory}/storage/fonts/" (在config/dompdf.php中可用)
- chroot: "{app_directory}" (在config/dompdf.php中可用)
- logOutputFile: "/tmp/log.htm"
- defaultMediaType: "screen" (在config/dompdf.php中可用)
- defaultPaperSize: "a4" (在config/dompdf.php中可用)
- defaultFont: "serif" (在config/dompdf.php中可用)
- dpi: 96 (在config/dompdf.php中可用)
- fontHeightRatio: 1.1 (在config/dompdf.php中可用)
- isPhpEnabled: false (在config/dompdf.php中可用)
- isRemoteEnabled: true (在config/dompdf.php中可用)
- isJavascriptEnabled: true (在config/dompdf.php中可用)
- isHtml5ParserEnabled: false (在config/dompdf.php中可用)
- isFontSubsettingEnabled: false (在config/dompdf.php中可用)
- debugPng: false
- debugKeepTemp: false
- debugCss: false
- debugLayout: false
- debugLayoutLines: true
- debugLayoutBlocks: true
- debugLayoutInline: true
- debugLayoutPaddingBox: true
- pdfBackend: "CPDF" (可在 config/dompdf.php 中配置)
- pdflibLicense: ""
- adminUsername: "user"
- adminPassword: "password"
请参考Dompdf\Options以获取可用选项列表。
方法
所有方法都可通过 Facade 类 Renatio\DynamicPDF\Classes\PDF
获取。
提示
背景图片
要显示布局中添加的背景图片,请使用以下代码
<body style="background: url({{ background_img }}) top left no-repeat;">
背景图片至少应为 96 DPI 大小(793 x 1121 px)。
如果您想使用更高分辨率的图片,如 300 DPI(2480 x 3508 px),则需要更改模板选项,如下所示
return PDF::loadTemplate($model->code)
->setDpi(300)
->stream();
UTF-8 支持
在您的布局中,在 head
部分设置 UTF-8 元标签
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
如果您遇到外文字符问题,请尝试使用 DejaVu Sans 字体族。
分页
您可以使用 CSS 的 page-break-before/page-break-after 属性创建新页面。
<style>
.page-break {
page-break-after: always;
}
</style>
<h1>Page 1</h1>
<div class="page-break"></div>
<h1>Page 2</h1>
基于目录的开放限制错误
在一些主机提供商上,有关于日志文件中 open_basedir
限制问题的报告。您可以更改默认日志文件目标,如下所示
return PDF::loadTemplate('renatio::invoice')
->setLogOutputFile(storage_path('temp/log.htm'))
->stream();
在 PDF 模板中嵌入图片
您可以使用绝对路径,例如 https://app.dev/path_to_your_image
。
为了使此功能正常工作,您必须设置 isRemoteEnabled
选项。
return PDF::loadTemplate('renatio::invoice', ['file' => $file])
->setIsRemoteEnabled(true)
->stream();
我假设 $file
是 October\Rain\Database\Attach\File
的实例。
然后在模板中,您可以使用以下示例代码
{{ file.getPath }}
{{ file.getLocalPath }}
{{ file.getThumb(200, 200, {'crop' => true}) }}
为了通过 HTTP 获取样式表或图片,必须启用以下 PHP 设置
allow_url_fopen
。
如果服务器上禁用了 allow_url_fopen
,请尝试使用相对路径。您可以使用 October 的 getLocalPath
函数在文件对象上获取它。
通过 Ajax 响应下载 PDF
OctoberCMS Ajax 框架无法处理此类响应。
建议的方法是将 PDF 文件本地保存并返回到 PDF 文件的重定向。
页码
可以使用 PHP 生成页码。默认情况下,内联 PHP 已禁用,因为它可能是一个安全风险。您可以使用 setIsPhpEnabled
方法启用内联 PHP。
return PDF::loadTemplate('renatio::invoice')
->setIsRemoteEnabled(true)
->setIsPhpEnabled(true)
->stream();
之后,您必须在布局文件的 </body>
标签之前放置以下代码。
<script type="text/php">
if (isset($pdf)) {
$size = 9;
$color = [0,0,0];
$font = $fontMetrics->getFont('Open Sans');
$textHeight = $fontMetrics->getFontHeight($font, $size);
$width = $fontMetrics->getTextWidth('Page 1 of 2', $font, $size);
$foot = $pdf->open_object();
$w = $pdf->get_width();
$h = $pdf->get_height();
$y = $h - $textHeight - 13;
$pdf->close_object();
$pdf->add_object($foot, 'all');
$text = "Page {PAGE_NUM} of {PAGE_COUNT}";
// Center the text
$pdf->page_text($w / 2 - $width / 2, $y, $text, $font, $size, $color);
}
</script>
示例
演示示例
有一个控制台命令可以启用演示模板和布局。
php artisan dynamicpdf:demo
要禁用演示,请运行以下命令
php artisan dynamicpdf:demo --disable
第一个示例显示了带有自定义字体和图片嵌入的发票。
第二个示例显示了使用页眉和页脚、分页、页码和全背景图片的用法。
在浏览器中渲染 PDF
use Renatio\DynamicPDF\Classes\PDF; // import facade
public function pdf()
{
$templateCode = 'renatio::invoice'; // unique code of the template
$data = ['name' => 'John Doe']; // optional data used in template
return PDF::loadTemplate($templateCode, $data)->stream('download.pdf');
}
其中 $templateCode
是创建模板时指定的唯一代码,$data
是可选的 twig 字段数组,它将在模板中替换。
在 HTML 模板中,您可以使用 {{ name }}
输出 John Doe
。
下载 PDF
use Renatio\DynamicPDF\Classes\PDF;
public function pdf()
{
return PDF::loadTemplate('renatio::invoice')->download('download.pdf');
}
流畅接口
您可以链式调用方法
return PDF::loadTemplate('renatio::invoice')
->save('/path-to/my_stored_file.pdf')
->stream();
更改纸张大小和方向
return PDF::loadTemplate('renatio::invoice')
->setPaper('a4', 'landscape')
->stream();
支持的 纸张大小。
在 CMS 页面上显示 PDF
要显示 CMS 页面上的 PDF,您可以使用页面上的 PHP 部分,如下所示
use Renatio\DynamicPDF\Classes\PDF;
function onStart()
{
return PDF::loadTemplate('renatio::invoice')->stream();
}
每页的页眉和页脚
<html>
<head>
<style>
@page { margin: 100px 25px; }
header { position: fixed; top: -60px; left: 0px; right: 0px; background-color: lightblue; height: 50px; }
footer { position: fixed; bottom: -60px; left: 0px; right: 0px; background-color: lightblue; height: 50px; }
p { page-break-after: always; }
p:last-child { page-break-after: never; }
</style>
</head>
<body>
<header>header on each page</header>
<footer>footer on each page</footer>
<main>
<p>page1</p>
<p>page2</p>
</main>
</body>
</html>
使用自定义字体
插件提供 "Open Sans" 字体,您可以在布局 CSS 部分导入。
@font-face {
font-family: 'Open Sans';
src: url({{ 'plugins/renatio/dynamicpdf/assets/fonts/OpenSans-Regular.ttf'|app }});
}
@font-face {
font-family: 'Open Sans';
font-weight: bold;
src: url({{ 'plugins/renatio/dynamicpdf/assets/fonts/OpenSans-Bold.ttf'|app }});
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
src: url({{ 'plugins/renatio/dynamicpdf/assets/fonts/OpenSans-Italic.ttf'|app }});
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: bold;
src: url({{ 'plugins/renatio/dynamicpdf/assets/fonts/OpenSans-BoldItalic.ttf'|app }});
}
body {
font-family: 'Open Sans', sans-serif;
font-size: 16px;
}