littlerocket/php-pdf

PHP的PDF和图形文件生成库。已针对PHP7进行修复

1.1.1 2023-04-12 08:38 UTC

This package is auto-updated.

Last update: 2024-09-12 11:48:20 UTC


README

示例

示例文档位于 "examples" 目录中。 "index.php" 文件是浏览示例的Web界面,"cli.php" 是控制台界面。通过Web界面,文档以PDF和jpeg格式提供(jpeg格式需要Imagick)。

文档

目录

  1. 介绍
  2. 安装
  3. Symfony2组件
  4. 常见问题解答
  5. 文档解析和创建PDF文件
  6. 基本文档结构
  7. 继承
  8. 样式表结构
  9. 颜色调板
  10. 标准标签
  11. 属性
  12. 复杂属性
  13. 单位
  14. 条形码
  15. 图表
  16. 超链接
  17. 书签
  18. 便签
  19. 重复的页眉和页脚
  20. 水印
  21. 页码
  22. 将PDF文档用作模板
  23. 分栏页面
  24. 断页和断栏
  25. 元数据
  26. 配置
  27. Markdown支持
  28. [图像生成引擎] (#image-generation)
  29. 已知限制
  30. 待办事项 - 计划
  31. 技术要求

介绍

PHPPdf是一个库,可以将XML文档转换为PDF文档或图形文件。XML源文档类似于HTML,但在标签名称和属性属性、标签属性以及许多非标准标签方面存在许多差异,并非所有HTML标签都受支持,样式表由XML文档描述,而不是CSS。

此库的假设不是HTML -> PDF / JPEG / PNG,而是XML -> PDF / JPEG / PNG转换。一些标签和属性与HTML中相同,以降低该库的学习曲线。

安装

PHPPdf可在packagist.org上找到,因此您可以使用composer下载此库及其所有依赖项。

(在您的composer.json文件的require部分添加)

    "littlerocket/php-pdf": "*"

您应选择最后一个稳定版本(或稳定版本的通配符),通配符字符 ("*") 仅是示例。

如果您想使用条形码或图像生成等特性,您应添加额外的依赖项

    "zendframework/zend-barcode": ">=2.0.0,<2.4",
    "zendframework/zend-validator": ">=2.0.0,<2.4",
    "imagine/Imagine": ">=0.2.0,<0.6.0"

Symfony2组件

存在一个 Symfony2组件,该组件将此库与Symfony2框架集成。

常见问题解答

重音符号不显示,我该怎么做?

您应设置一个支持您使用的编码的字体,并将此编码设置为 "page" 和/或 "dynamic-page" 标签的 "encoding" 属性。PHPPdf提供了一些支持utf-8编码的免费字体,例如,DejaVuSans。 "Font" 示例显示了如何通过使用样式表来更改字体类型。

您还可以添加自定义字体,为此您应准备xml配置文件并按以下方式配置Facade对象

    <!-- xml config file code -->
    <fonts>
        <font name="DejaVuSans">
            <normal src="%resources%/fonts/DejaVuSans/normal.ttf" /><!-- "%resources%" will be replaced by path to PHPPdf/Resources directory -->
            <bold src="%resources%/fonts/DejaVuSans/bold.ttf" />
            <italic src="%resources%/fonts/DejaVuSans/oblique.ttf" />
            <bold-italic src="%resources%/fonts/DejaVuSans/bold+oblique.ttf" />
            <light src="%resources%/fonts/DejaVuSans/light.ttf" />
            <light-italic src="%resources%/fonts/DejaVuSans/light+oblique.ttf" />
        </font>
    </fonts>
//php code
$loader = new PHPPdf\Core\Configuration\LoaderImpl();
$loader->setFontFile(/* path to fonts configuration file */);
$builder = PHPPdf\Core\FacadeBuilder::create($loader);
$facade = $builder->build();
<!-- xml document code -->
<pdf>
    <dynamic-page encoding="UTF-8" font-type="DejaVuSans">
    </dynamic-page>
</pdf>

您可以在 配置 部分找到更多详细信息。

生成带有png图像的简单PDF文件需要很多时间和内存,我该怎么做?

PHPPdf使用Zend_Pdf库,该库对未压缩的png文件支持不佳。您应压缩png文件。

我如何更改页面大小/方向?

要设置页面尺寸,您可以使用页面或动态页面标签的“page-size”属性。

该属性的值语法是“width:height”。

但是,也有一些标准预定义值

  • 格式:从4A0到A10
  • B格式:从B0到B10
  • C格式:从C0到C10
  • 美国尺寸:法律和信函

所有格式都支持纵向和横向。

示例

<page page-size="100:50">text</page>
<page page-size="a4">text</page>
<page page-size="letter-landscape">text</page>

文档解析和创建PDF文件

使用库的最简单方法是

//register the PHPPdf and vendor (Zend_Pdf and other dependencies) autoloaders
require_once 'PHPPdf/Autoloader.php';
PHPPdf\Autoloader::register();
PHPPdf\Autoloader::register('/path/to/library/lib/vendor/Zend/library');

//if you want to generate graphic files
PHPPdf\Autoloader::register('sciezka/do/biblioteki/lib/vendor/Imagine/lib');

$facade = new PHPPdf\Core\Facade(new PHPPdf\Core\Configuration\Loader());

//$documentXml and $stylesheetXml are strings contains XML documents, $stylesheetXml is optional
$content = $facade->render($documentXml, $stylesheetXml);

header('Content-Type: application/pdf');
echo $content;

基本文档结构

该库基于与HTML类似的XML格式,但这不是HTML - 一些标签是不同的,一些属性的解析与HTML和CSS标准不同,添加属性的方式也不同。

一个简单的文档具有以下结构

<pdf>
    <dynamic-page>
        <h1>Header</h1>
        <p>paragraph</p>
        <div color="red">Layer</div>
        <table>
            <tr>
                <td>Column</td>
                <td>Column</td>
            </tr>
        </table>
    </dynamic-page>
</pdf>

强烈建议添加DOCTYPE声明,以便在值上替换HTML实体

    <!DOCTYPE pdf SYSTEM "%resources%/dtd/doctype.dtd">

文档的根名称必须是“pdf”。 "dynamic-page"标签是一个可自动换行的页面。 "page"标签是另一种选择,表示仅一个不可换行的页面。

属性设置的格式与HTML不同。

为了设置背景和边框,您需要使用复杂的属性,其中属性名的第一部分是复杂的属性类型,第二部分是该属性的属性。

复杂的属性部分由点(“.”)分隔。

设置复杂属性的另一种方法是使用“complex-attribute”标签。

示例

<pdf>
    <dynamic-page>
        <div color="red" border.color="black" background.color="pink">
            This text is red on pink backgroun into black border
        </div>
    </dynamic-page>
</pdf>

替代语法(“stylesheet”标签)

<pdf>
    <dynamic-page>
        <div>
            <stylesheet>
                <attribute color="red" />
                <complex-attribute name="border" color="black" />
                <complex-attribute name="background" color="pink" />
            </stylesheet>
            This text is red on pink backgroun into black border
        </div>
    </dynamic-page>
</pdf>

属性可以作为XML属性设置,直接在标签名之后,或使用提到的“stylesheet”标签。PHPPdf XML方言中没有HTML的“style”属性。

该库在尊重标签和属性的准确性方面非常严格。如果检测到不存在标签或属性,文档解析器将停止并抛出异常。

继承

“id”属性在HTML中的使用与不同。id属性用于在继承中使用时标识标签。

“name”属性也可以用作“id”的别名。

id在整个文档中必须是唯一的,否则将抛出解析错误。

示例

<pdf>
    <dynamic-page>
        <div id="layer-1" color="red" font-type="judson" font-size="16px">
            <stylesheet>
                <complex-attribute name="border" color="green" />
            </stylesheet>
            Layer 1
        </div>
        <div extends="layer-1">
            Layer 2 inherits style (type, simple and complex attributes) from layer 1)
        </div>
    </dynamic-page>
</pdf>

第二层继承所有属性(简单和复杂),以及来自外部样式表的属性。

属性设置中的优先级

  1. 元素标签中的“stylesheet”标签
  2. 标签名后的属性(XML属性)
  3. 来自外部样式表的属性
  4. 从父标签继承的属性

示例

<pdf>
    <page>
        <div id="1" color="#cccccc" height="100px" text-align="right">
        </div>
        <div extends="1" color="#aaaaaa" height="150px">
            <stylesheet>
                <attribute name="height" value="200px" />
            </stylesheet>
        </div>
    </page>
</pdf>

第二个“div”现在将具有以下属性

  • text-align: right
  • color: #aaaaaa
  • height: 200px

样式表结构

样式表定义在外部文件中,支持样式表的简短和长属性声明。

样式表的语法

简短样式

<stylesheet>
    <!-- style attributes are embeded as xml attributes, class attribute has the same meaning as in HTML/CSS -->
    <div class="class" font-size="12px" color="gray" background.color="yellow">
        <!-- nested element, equivalent CSS selector syntax: "div.class p" -->
        <p margin="10px 15px">
        </p>
    </div>

    <!-- equivalent CSS selector syntax: ".another-class", "any" tag is wildcard (mean any tag) -->
    <any class="another-class" text-align="right">
    </any>

    <h2 class="header">
        <span font-size="9px">
        </span>
        
        <div font-style="bold">
        </div>
    </h2>
</stylesheet>

长样式

<stylesheet>
    <div class="class">
        <!-- simple and complex attributes are nested in "div.class" selector path -->
        <attribute name="font-size" value="12px" />
        <attribute name="color" value="grey" />
        <!-- equivalent of background.color attribute -->
        <complex-attribute name="background" color="yellow" />

        <!-- another nested element, equivalent CSS selector syntax: "div.class p" -->
        <p>
            <attribute name="margin" value="10px 15px" />
        </p>
    </div>

    <!-- equivalent CSS selector syntax: ".another-class", "any" tag is wildcard (mean any tag) -->
    <any class="another-class">
        <attribute name="text-align" value="right" />
    </any>

    <h2 class="header">
        <span>
            <attribute name="font-size" value="9px" />
        </span>
        <div>
            <attribute name="font-style" value="bold" />
        </div>
    </h2>
</stylesheet>

颜色调

PHPPdf支持颜色调色板,即逻辑名称到真实颜色的映射。

颜色调色板让您有机会创建或覆盖默认命名的颜色。默认情况下,PHPPdf支持W3C标准中的命名颜色(例如“black” = "#000000")。

您可以使用调色板实现DRY原则,因为关于使用颜色的信息将保存在一个地方。您还可以使用不同的调色板生成一个文档。

示例

<!-- colors.xml file -->
<colors>
    <color name="header-color" hex="#333333" />
    <color name="line-color" hex="#eeeeee" />
</colors>

<!-- stylesheet.xml file -->
<h2 color="header-color" />
<hr background-color="line-color" />
<table>
    <td border-color="line-color" />
</table>

<!-- document.xml file -->
<pdf>
    <page>
        <h2>Header</h2>
        <hr />
        <table>
            <tr>
                <td>Data</td>
                <td>Data</td>
            </tr>
        </table>
    </page>
</pdf>
    //php code
    use PHPPdf\DataSource\DataSource;
    
    $facade = ...;

    $content = $facade->render(
        DataSource::fromFile(__DIR__.'/document.xml'),
        DataSource::fromFile(__DIR__.'/stylesheet.xml'),
        DataSource::fromFile(__DIR__.'/colors.xml')
    );

标准标签

该库支持主要的HTML标签:div, p, table, tr, td, b, strong, span, a, h1, h2, h3, h4, h5, img, br, ul, li

此外,还有一些非标准标签

  • dynamic-page - 可自动换行的页面
  • 页面 - 单页,具有固定大小
  • 弹性页 - 单页可以适应其子元素的高度,与其它标签(如“div”)相同。标题、页脚、水印、模板文档属性不适用于此标签。特别适用于图形文件生成(图像引擎)。
  • 页面分割、列分割、分割 - 分割页面或列,此标签必须是“动态页面”或“列布局”的直接子元素!
  • 列布局 - 在列上分离工作区,附加属性:列数、列间距、等宽列
  • 条形码 - 更多信息请参阅条形码章节
  • 圆形 - 边框和背景为圆形的元素。附加属性:半径(它覆盖宽度和高度属性)
  • 饼图 - 可以用来绘制简单饼图的元素(更多信息请参阅图表章节)。

有一些标签只用于属性,一组标签等

  • 样式表 - 父元素的样式表
  • 属性 - 简单属性声明,为“样式表”标签的直接子元素。此元素必需的属性:name - 属性名称,value - 属性值
  • 复杂属性 - 复杂属性声明,为“样式表”标签的直接子元素。此元素必需的属性:name - 复杂属性名称
  • 占位符 - 定义父标签的占位符。占位符的子标签对每个父标签都是特定的。它应该是父标签的第一个标签
  • 元数据 - 定义PDF文档的元数据,为文档根的直接子元素
  • 行为 - 定义父标签的行为。支持的行为:href、ref、书签、笔记(动作与具有相同名称的属性相同)

属性

  • 宽度与高度:严格设置高度和宽度,支持的单位在单独的章节中描述。支持相对值百分比。
  • 最大宽度、最大高度:设置元素的最大尺寸
  • 边距(上边距、下边距、左边距、右边距):类似于HTML/CSS中的边距。相似元素的边距会合并。对于侧边距,可能的值为“auto”,其工作方式类似于HTML/CSS。
  • 内边距(上内边距、下内边距、左内边距、右内边距):与HTML/CSS中类似
  • 字体类型 - 字体名称必须在fonts.xml配置文件中存在,否则将抛出异常
  • 字体大小 - 文件大小以点为单位,没有单位
  • 字体样式 - 允许的值:正常、粗体、斜体、粗斜体、轻、轻斜体
  • 颜色 - 文本颜色。支持HTML/CSS样式值
  • 可分割 - 如果为true,则元素可以在多个页面中分割。大多数标签的默认值是true。
  • 浮动 - 与HTML/CSS类似但不同。允许的值:左|无|右,默认无
  • 行高 - 与HTML/CSS类似。默认值:1.2*字体大小
  • 文本对齐 - 与HTML/CSS相同。允许的值:左|居中|右|两端对齐,默认左。
  • 文本装饰 - 允许的值:无、下划线、上划线、删除线
  • 分割 - 在具有此属性的元素的末尾分割页面或列。具有此属性的元素必须是动态页面或列布局标签的直接子元素!
  • colspan、rowspan - 与HTML类似(待办:rowspan尚未实现)
  • href - 元素应链接的外部URL
  • ref - 应链接的元素的ID
  • 书签 - 创建与给定标题相关联的标签的书签
  • 笔记 - 创建与标签相关联的粘性笔记
  • dump - 允许的值:true或false。创建带有调试信息(属性、位置等)的粘性笔记
  • 旋转 - 元素旋转的角度。此属性尚未完全实现,水印(请参阅“水印”部分)中工作正确。可能的值:XX度(度),XX(弧度),对角线,-对角线。
  • alpha - 可能的值:从0到1。元素及其子元素的不透明度。
  • 换行符 - 是否进行换行(true或false),默认仅对"br"标签设置为true
  • 样式 - 与HTML中相同,此属性可以用来设置其他属性,例如:style="width: 100px; height: 200px; margin: 20px 0;"。每个属性必须以";"字符结尾,即使是最后一个。
  • 忽略错误(仅对img标签有效) - 忽略文件加载错误或抛出异常?默认为false,这意味着会抛出异常。
  • 保持比例(仅对img标签有效) - 即使设置的尺寸比例与原始源图像的比例不同,也会通过裁剪图像片段来保持比例。默认为false。
  • 位置 - 与HTML中相同。允许的值:static(默认),relative,absolute
  • left和top - 与HTML中相同,与position relative或absolute一起使用。right和bottom不支持。

复杂属性

可以通过"attributeName.attributeProperty"或"attributeName-attributeProperty"的表示法设置复杂属性。

例如:border.color="black"border-color="black"

  • border

    • 颜色:边框颜色
    • 样式:可能的值:solid(实线),dotted(预定义的点线)或任何由空格分隔的整数定义
    • 类型:显示哪些边缘 - 默认值为"top+bottom+left+right"(所有边缘)。"none"值是可能的(它禁用边框)
    • 大小:边框大小
    • 半径:以长度单位为单位的角圆度(注意:如果设置了此参数,则忽略type参数,圆角边框始终是完整的 - 这将在未来修复)
    • 位置:相对于原始位置的边框平移。正值扩展边框,负值减少边框。通过此参数的调整,您可以通过添加不同样式和位置的另一个边框来获得复杂的边框模式。
  • 背景

    • 颜色:背景颜色
    • 图像:背景图像
    • 重复:图像重复的方式(none|x|y|all)
    • 半径:以长度单位为单位的背景角圆度(目前仅适用于颜色背景)
    • use-real-dimension:仅用于页面(或动态页面)的属性。用于填充时为true,否则为false。
    • image-width:自定义背景图像的宽度,允许使用百分比值
    • image-height:自定义背景图像的高度,允许使用百分比值
    • position-x:背景图像的水平位置,允许的值:left,center,right或数值(默认:left)
    • position-y:背景图像的垂直位置,允许的值:top,center,bottom或数值(默认:top)

可以在同一类型中添加多个复杂属性(例如,3个不同的边框)。

您可以通过使用"stylesheet"标签而不是简写表示法来实现这一点。

<pdf>
    <dynamic-page>
        <div>
            <stylesheet>
                <!-- Top and bootom edges are red, side edges are yellow-gray --> 
                <complex-attribute name="border" color="red" type="top+bottom" />
                <complex-attribute id="borderLeftAndRight" name="border" color="yellow" type="left+right" size="4px" />
                <complex-attribute id="outerBorderLeftAndRight" name="border" color="gray" type="left+right" size="2px" position="1px" />
            </stylesheet>
        </div>
    </dynamic-page>
</pdf>

在这个例子中,第二个边框有一个"borderLeftAndRight"标识符,如果这个边框没有id,第二个边框的属性将合并到第一个边框的属性中。

记住默认标识符"id"与"name"属性相同。复杂属性的"id"属性与标签的"id"属性(用于继承)无关。

可以创建与上一个示例(outerBorderLeftAndRight)相同的复杂边框。

单位

支持的数值属性单位

  • in(英寸)
  • cm(厘米)
  • mm(毫米)
  • pt(点)
  • pc(派卡)*
  • px(像素)
    • %(百分比 - 仅用于宽度和高度)。

当前不支持的单位是:em和ex

如果缺少单位(例如:font-size="10"),则默认单位是点(pt)。1pt = 1/72英寸

条码

条码通过<barcode>标签支持。

PHPPdf使用Zend\Barcode库来生成条码。

示例

<pdf>
    <dynamic-page>
        <barcode type="code128" code="PHPPdf" />
    </dynamic-page>
</pdf>

<barcode> 标签支持大多数标准属性,还有一些其他属性

  • type - 条码类型,支持的值:code128, code25, code25interleaved, code39, ean13, ean2, ean5, ean8, identcode, itf14, leitcode, planet, postnet, royalmail, upca, upce
  • draw-code - 与 Zend\Barcode 的 drawCode 选项等价
  • bar-height - 与 Zend\Barcode 的 barHeight 选项等价
  • with-checksum - 与 Zend\Barcode 的 withChecksum 选项等价
  • with-checksum-in-text - 与 Zend\Barcode 的 withChecksumInText 选项等价
  • bar-thin-width - 与 Zend\Barcode 的 barThinWidth 选项等价
  • bar-thick-width - 与 Zend\Barcode 的 barThickWidth 选项等价
  • rotate - 与 Zend\Barcode 的 orientation 选项等价

您可以在 Zend\Barcode 文档 中找到这些选项的描述及其默认值。

为了渲染文本条码,您不能使用以下嵌入的 PDF 字体:courier、times-roman 和 helvetica。这将被很快修复。

图表

PHPPdf 支持绘制简单的图表。

目前只支持简单的饼图。

示例

<pdf>
    <dynamic-page>
        <pie-chart radius="200px" chart-values="10|20|30|40" chart-colors="black|red|green|blue"></pie-chart>
    </dynamic-page>
</pdf>

<pie-chart> 标签有三个额外属性

  • radius - 图表的半径
  • chart-values - 图表值,总和必须为 100。每个值必须由 "|" 分隔。
  • chart-colors - 每个值的颜色。每个颜色必须由 "|" 分隔。

超链接

库支持外部和内部超链接。

外部超链接链接到 URL,而内部链接链接到 PDF 文档内的其他标签。

示例

<pdf>
    <dynamic-page>
        <a href="http://google.com">go to google.com</a>
        <br />
        <a ref="some-id">go to another tag</a>
        <a href="#some-id">go to another tag</a> <!-- anchor style ref -->
        <page-break />
        <p id="some-id">Yep, this is another tag! ;)</p>
    </dynamic-page>
</pdf>

每个元素都有一个 "href" 和 "ref" 属性,即使是 div。您不能在 "a" 标签内嵌套元素。

如果您想使用 img 元素作为链接,您应该在 img 标签中直接使用 href(外部链接)或 ref(内部链接)属性。

书签

创建书签的首选方法是使用 "behaviours" 标签。

这不会限制文档的结构,父书签的所有者不必是子书签所有者的父级。

示例

<pdf>
    <dynamic-page>
	    <div>
	        <behaviours>
	            <bookmark id="1">parent bookmark</bookmark>
	        </behaviours>
	        Some content
	    </div>
	    <div>
	        <behaviours>
	            <bookmark parentId="1">children bookmark</bookmark>
	        </behaviours>
	        Some another content
	    </div>
	    <div>
	        <behaviours>
	            <bookmark parentId="1">another children bookmark</bookmark>
	        </behaviours>
	        Some another content
	    </div>
	    <div>
	        <behaviours>
	            <bookmark>another parent bookmark</bookmark>
	        </behaviours>
	       Some content
	    </div>
	</dynamic-page>
</pdf>

"bookmark" 行为的快捷方式是 "bookmark" 属性,如果您为此属性分配了一些值,则引用此标签的书签将自动创建。

父标签的书签也是子书签的父级。

示例

<pdf>
    <dynamic-page>
	    <div bookmark="parent bookmark">
	        Some content
	        <div bookmark="children bookmark">
	            Some another content
	        </div>
	        <div bookmark="another children bookmark">
	            Some another content
	        </div>
	    </div>
	    <div bookmark="another parent bookmark">
	       Some content
	    </div>
	</dynamic-page>
</pdf>

上述结构(两个示例)将创建以下书签结构

  • 父书签
    • 子书签
    • 另一个子书签
  • 另一个父书签

便签

可以通过使用 "note" 属性来创建便签。

示例

<pdf>
    <dynamic-page>
        <div note="note text"></div>
    </dynamic-page>
</pdf>

XML 解析器会规范化属性值,这导致忽略换行符。

如果您想添加包含换行符的注释,您应该使用此语法

<pdf>
    <dynamic-page>
        <div>
            <behaviours>
                <note>note text</note>
            </behaviours>
        </div>
    </dynamic-page>
</pdf>

重复的页眉和页脚

"占位符" 可以用于添加重复的页眉或页脚。

某些元素有特殊的 "占位符":页面有页眉和页脚,表格也有页眉和页脚(待实现)等。

<pdf>
    <dynamic-page>
        <placeholders>
            <header>
                <div height="50px" width="100%">
                    Header
                </div>
            </header>
            <footer>
                <div height="50px" width="100%">
                    Footer
                </div>
            </footer>
        </placeholders>
    </dynamic-page>
</pdf>

页眉和页脚需要设置一个高度属性。这个高度与页面的顶部和底部边距一起使用。

工作区是页面大小减去页面边距和占位符(页脚和页眉)高度。

水印

页面可以有一个 "watermark" 占位符。

水印可以设置在块和容器元素上,例如:div、p、h1(不包括 span、纯文本或 img)。

如果您想使用图像作为水印,您应该将 img 标签包裹在一个 div 中。

示例

<pdf>
    <dynamic-page>
        <placeholders>
            <watermark>
                <!-- rotate can have absolute values (45deg - in degrees, 0.123 - in radians) or relative values ("diagonally" and "-diagonally" - angle between diagonal and base side of the page) -->
                <div rotate="diagonally" alpha="0.1">
                    <img src="path/to/image.png" />
                </div>
            </watermark>
        </placeholders>
    </dynamic-page>
</pdf>

页码编号

有两个标签可以用于在页脚、页眉或水印中显示页面信息:page-info 和 page-number。

此元素仅与动态页面兼容,不与单页兼容。页面信息显示当前页和总页数,页面编号仅显示当前页数。

此标签的属性

  • format - 输出字符串的格式,该字符串将用作 sprintf 函数的参数。默认值:"%s." 用于页面编号,"%s / %s" 用于页面信息。
  • offset - 将添加到当前页数和总页数的值。如果您想从非零值开始计数页面,则很有用。默认值:0。

示例

<pdf>
    <dynamic-page>
        <placeholders>
            <header>
                <div height="20px">
                    <page-info format="page %s for %s" />

                    <!-- when we would like to number from 2 -->
                    <page-info offset="1" format="page %s for %s" />

                    <!-- when we would like to display only current page number -->
                    <page-info format="%1$s." />
                    <!-- or -->
                    <page-number />

                    <!-- when we would like to display only total pages number -->
                    <page-info format="%2$s pages" />
                </div>
            </header>
        </placeholders>
        Some text
    </dynamic-page>
</pdf>

使用 PDF 文档作为模板

"page" 和 "dynamic-page" 标签可以有一个 "document-template" 属性,允许您使用外部 PDF 文档作为模板。

对于 "page" 标签,页面的模板将是外部文档的第一页。

对于 "dynamic-page" 标签,每页的模板将是外部文档的对应页。

示例

<pdf>
    <dynamic-page document-template="path/to/file.pdf">
        <div>Some content</div>
    </dynamic-page>
</pdf>

列表中的单独页面

页面可以按列分隔

<pdf>
    <dynamic-page>
        <column-layout>
            <div width="100%" height="2500px" background.color="green">
            </div>
        </column-layout>
    </dynamic-page>
</pdf>

上述 XML 描述了 PDF 文档的几页,其中绿色矩形按两列分隔。

"column-layout" 标签有三个额外的参数:number-of-columns(列数)、margin-between-columns(列间距)和equals-columns(等高列)。

这些属性的默认值分别为 2、10 和 false。如果设置了 equals-columns 属性,则列的高度将大致相等。

分割页面和列

可以使用以下标签之一手动分割页面和列:page-break、column-break、break。

所有这些标签都是相同的。这些标签必须是分割元素(dynamic-page 或 column-layout)的直接子元素。

如果您想避免在特定标签上自动分割页面或列,应将此标签的 "breakable" 属性设置为 "off"。

示例

<pdf>
    <dynamic-page>
        <div breakable="false">this div won't be automatically broken</div>
    </dynamic-page>
</pdf>

元数据

可以通过文档根的属性添加元数据。

支持以下元数据:Creator、Keywords、Subject、Author、Title、ModDate、CreationDate 和 Trapped。

** 这些属性名称区分大小写。 **

示例

<pdf Author="Piotr Sliwa" Title="Test document">
    <!-- some other elements -->
</pdf>

配置

该库有四个主要配置文件,允许您根据特定需求采用库并扩展。

  • complex-attributes.xml - 复杂属性类声明的声明,以逻辑名称标识整个库中的属性。
  • nodes.xml - XML 文档中允许的标签的定义,包括默认属性和格式化对象。
  • fonts.xml - 字体的定义和分配给整个库中的字体的逻辑名称。
  • colors.xml - 颜色定义调色板

要更改默认配置文件,必须将配置的 Loader 对象传递给 Facade 构造函数。

    $loader = new PHPPdf\Core\Configuration\LoaderImpl(
        '/path/to/file/nodes.xml',
        '/path/to/file/enhancements.xml',
        '/path/to/file/fonts.xml',
        '/path/to/file/colors.xml'
    );
    
    $facade = new PHPPdf\Core\Facade($loader);

如果您只想更改一个配置文件,应使用 LoaderImpl::set* 方法。

$loader = new PHPPdf\Core\Configuration\LoaderImpl();
$loader->setFontFile(
'/path/to/file/fonts.xml'); //there are setFontFile, setNodeFile, setComplexAttributeFile and setColorFile methods
$facade = new PHPPdf\Core\Facade($loader);

FacadeBuilder 可以用于构建和配置 Facade。FacadeBuilder 能够配置缓存、渲染引擎和文档解析器。

$builder = PHPPdf\Core\FacadeBuilder::create(/* you can pass specyfic configuration loader object */)
                                        ->setCache('File', array('cache_dir' => './cache'))
                                        ->setUseCacheForStylesheetConstraint(true); //stylesheets will be also use cache

$facade = $builder->build();

Markdown 支持

库支持基本(官方)markdown 语法。要将 markdown 文档转换为 pdf,您应通过 MarkdownDocumentParser 配置 Facade 对象。您还可以使用 FacadeBuilder 来完成此操作。

示例

$facade = PHPPdf\Core\FacadeBuilder::create()
                                   ->setDocumentParserType(PHPPdf\Core\FacadeBuilder::PARSER_MARKDOWN)
                                   ->setMarkdownStylesheetFilepath(/** optionaly path to stylesheet in xml format */)
                                   ->build();

默认情况下,在 markdown pdf 文档中,使用 helvetica 字体。如果您想使用 utf-8 字符或自定义 pdf 文档,您应通过 FacadeBuilder::setMarkdownStylesheetFilepath 方法提供自己的样式表。

样式表结构已在 样式表 章节中描述。默认情况下,样式表为空,如果想要设置其他字体类型,样式表应如下所示

<stylesheet>
    <any font-type="DejaVuSans" />
</stylesheet>

内部,MarkdownDocumentParser 将 markdown 文档转换为 html(通过 PHP markdown 库),然后转换为 xml,最后转换为 pdf 文档。

请注意,如果在 markdown 文档中使用原始 html,可能会与 PHPPdf 的 xml 语法不兼容(例如不存在的属性或标签),此时解析器将抛出异常。

Not all tags used in the markdown implementation are propertly supported by PHPPdf, for example "pre" and "code" tags.
For now "pre" tag is an alias for "div", and "code" tag is an alias for "span", be aware of that.

图像生成引擎

PHPPdf 能够生成图像(jpg 或 png)文件而不是 pdf 文档。要实现这一点,您必须配置 FacadeBuilder,例如:

$facade = PHPPdf\Core\FacadeBuilder::create()
                                   ->setEngineType('image')
                                   ->build();

//render method returns array of images' sources, one pdf page is generated to single image file 
$images = $facade->render(...);

默认情况下使用 GD 库来渲染图像。

但您也可以使用 Imagick,它提供更好的质量,因此如果您有机会在服务器上安装 Imagick,建议使用 Imagick。要切换图形库,必须使用 setEngineOptions 方法配置 FacadeBuilder 对象。

$builder = ...;
$builder->setEngineOptions(array(
    'engine' => 'imagick',
    'format' => 'png',//png, jpeg or wbmp
    'quality' => 60,//int from 0 to 100
));

支持的图形库有:GD(默认),imagick,gmagick。PHPPdf 使用 Imagine 库作为图形文件生成的接口。

已知限制

以下是当前版本库的已知限制列表

  • 无法将图像注入到具有浮动属性的文字中——将在下一个版本中引入
  • 对表格元素内浮动属性的局部支持(浮动可能在表格内工作不正确)
  • 如果设置了此属性,则垂直对齐属性将不正确地工作,元素中有多个元素时
  • 边框不会改变元素的尺寸(而在 HTML 中则会改变)
  • png 文件(特别是没有压缩的)效率不高。建议使用具有高压缩(压缩级别 6 或更高)的 png 文件或 jpeg 文件
  • 并非所有标签都得到适当支持,例如 "pre" 标签是 "div" 的别名,而 "code" 标签是 "span" 的别名
  • 线性标签(text,span,code,page-info,page-number,a,b,i,em)的嵌套不支持。如果一个线性标签包含另一个标签,则仅合并此标签内的文本,样式取自最外层的线性标签。

TODO - 计划

  • 自动生成“目录”
  • 改进表格、页眉和页脚的表格、rowspan。修复使用 colspan 时单元格的最小高度计算。
  • 支持简单的条形图和饼图

技术要求

此库与 php 7.0 及以上版本兼容。