跳转到内容
getnextpdf.com

HTML 转 PDF,轻松之路

到目前为止,你在本系列中都是逐个调用地构建页面。许多文档若用标记语言(即网页所使用的、基于标签的文本格式)来描述会更快。在本教程中,你把一些 Hypertext Markup Language(HTML)交给 NextPDF,引擎便会为你绘制页面。

一份从单个 HTML 字符串渲染而来的单页报告。它包含一个彩色标题、一个简短段落, 以及一个带合计行的表格。你使用 Cascading Style Sheets(CSS,即控制标记外观的规则语言)为它设置样式。在之前的教程中,你使用的是流式 Application Programming Interface(API),也就是链式方法调用。而这里,你改用标记语言来描述布局,由同一个引擎来渲染它。

在你的项目文件夹中,与 vendor 并列,创建一个名为 01-html.php 的文件。 粘贴以下完整脚本:

<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
@mkdir(__DIR__ . '/out');
$document = Document::createStandalone();
$document->setTitle('Monthly reading report');
$document->addPage();
$html = <<<'HTML'
<h1 style="color: #1E3A8A;">Monthly reading report</h1>
<p>This report was rendered from <strong>HTML</strong> with inline
<em>CSS</em>. The table below lists two books and their page counts.</p>
<table border="1" cellpadding="5" cellspacing="0" style="width: 100%;">
<thead>
<tr style="background-color: #1E3A8A; color: #FFFFFF;">
<th style="width: 55%;">Title</th>
<th style="width: 20%; text-align: center;">Format</th>
<th style="width: 25%; text-align: right;">Pages</th>
</tr>
</thead>
<tbody>
<tr>
<td>The Paper Trail</td>
<td style="text-align: center;">Hardcover</td>
<td style="text-align: right;">312</td>
</tr>
<tr style="background-color: #F8FAFC;">
<td>Ink and Bytes</td>
<td style="text-align: center;">Paperback</td>
<td style="text-align: right;">248</td>
</tr>
</tbody>
<tfoot>
<tr style="font-weight: bold;">
<td colspan="2" style="text-align: right;">Total pages:</td>
<td style="text-align: right;">560</td>
</tr>
</tfoot>
</table>
HTML;
$document->writeHtml($html);
$document->save(__DIR__ . '/out/reading-report.pdf');
echo "Wrote out/reading-report.pdf\n";

在项目文件夹中运行脚本:

Terminal window
php 01-html.php

你应该会看到一行输出:

Wrote out/reading-report.pdf

在任意 Portable Document Format(PDF)查看器中打开 out/reading-report.pdf。 标题为深蓝色,表格的表头行也填充了相同的颜色。

  • @mkdir(__DIR__ . '/out'); 会创建输出文件夹。当文件夹已存在时,@ 符号会抑制警告,因此重复运行时不会有多余的输出。
  • Document::createStandalone()setTitle()addPage() 的用法与之前的教程完全相同。改用标记语言并不会改变你设置文档的方式。
  • writeHtml() 会从上到下将你的字符串读取一遍,并在当前位置绘制每个元素。 标题和段落会变成带样式的文本。表格则会变成一行行经过测量、带边框的单元格。
  • 内联的 style 属性承载了 CSS。引擎能够理解诸如 colorbackground-colortext-alignwidth 等常见属性。
  • 不涉及任何浏览器,也不需要任何额外软件。该管线是引擎内部的纯 PHP,因此只要你的 Composer 安装能运行的地方,脚本就能运行。

引擎支持 HTML 和 CSS 的一个实用子集,而非浏览器所接受的一切。该子集之外的任何内容都会被悄悄跳过,而不会引发错误。CSS 支持矩阵 准确记录了所涵盖的范围。若要更深入地了解这条管线,请参阅 将 HTML 渲染为 PDF 页面

两条路径都运行在同一个引擎上,因此选择适合你文档的那条即可。

  • 当文档读起来像一个网页时——包含标题、段落、列表和表格——就选择 writeHtml()。 标记语言编写起来更快,也更便于团队成员编辑。
  • 当你需要精确定位时——例如固定位置或精确测量的单元格——就选择流式 API。标记语言带给你的是流式排布,而流式调用带给你的是精确控制。
  • 在依赖某个属性之前,请查看 CSS 支持矩阵。 当某个样式未被涵盖时,请改用流式调用来构建这一部分。

真实的 HTML 往往来自你代码之外,例如来自表单或数据库。请将其视为不受信任的输入, 在渲染之前对其进行校验或清理。默认情况下,内置管线不运行任何脚本,也不获取任何远程资源。即使标记本身并不保守,这一默认设置也能让渲染器保持保守。如果你需要浏览器级别的渲染选项,请参阅 选择你的路径

  • Failed to open stream: No such file or directory 通常意味着脚本找不到 vendor/autoload.php。请在你运行 Composer 的那个文件夹中运行它。
  • 样式缺失通常是因为某个属性位于受支持的子集之外。引擎会跳过它不支持的内容, 而不是报错。请将你的标记与 CSS 支持矩阵 进行对照。
  • 渲染过程中抛出的异常会指明确切的问题。请在 渲染与输入/输出错误 参考中查找它。

对于其他任何情况,请从 故障排查指南 开始。

现在,你既能逐个调用地构建文档,也能从标记语言构建文档。请通过 接下来去哪里 完成本系列的学习。它梳理了你在本系列之后将会用到的操作手册、参考资料和指南。