添加书签与目录
本 recipe(示例)会添加一份分层文档大纲,也就是书签。阅读器应用会把这些条目列在导航侧栏中,它们同时构成可点击的目录。嵌套深度由整数层级控制。本示例遵循 examples/12-bookmarks-and-toc.php。
ISO 32000-2 将其称为文档大纲:由大纲项组成的树状层级,用作可视化目录。
composer require nextpdf/core:^3无需任何可选扩展。书签 API 自 1.0.0 起即为稳定版,可在 8.1–8.4 backport 兼容矩阵上运行。
概念说明
标题为“概念说明”的章节bookmark($title, $level, $y) 会添加一个绑定到当前页面的大纲项。这个绑定会使用当前 Y 坐标,也可以使用你显式指定的 Y 坐标。$level 用于设置嵌套深度:层级 0 是最顶层的章,层级 1 是隶属于最近一个层级 0 项的节,依此类推。引擎会替你构建大纲树。ISO 32000-2 在每一层使用 Prev/Next 串接各项,并通过 First/Last 形成嵌套,以 catalog 的 Outlines 项作为根节点。
每个项都带有一个目标位置,因此当你点击书签时,阅读器会跳转到正确页面。ISO 32000-2 §12.3.2 规定,目标位置可以与大纲项关联。同一次调用也会传给 NextPDF 的目录构建器,因此大纲与渲染出的目录会保持同步。
API 接口
标题为“API 接口”的章节API 接口由 PHPDoc 自动生成。本示例只依赖一个方法:
bookmark(string $title, int $level = 0, float $y = -1): static— 在$level层级添加一个绑定到当前页面的大纲项。$y = -1会使用当前光标的 Y 坐标。传入非负的 Y 值,即可固定精确的目标位置。
代码示例 — 快速上手
标题为“代码示例 — 快速上手”的章节<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->addPage();$doc->bookmark('Chapter 1', level: 0);$doc->setFont('helvetica', 'B', 18);$doc->cell(0, 12, 'Chapter 1', newLine: true);
$doc->bookmark('Section 1.1', level: 1); // nested under Chapter 1$doc->setFont('helvetica', '', 11);$doc->multiCell(0, 7, 'Section body.');
$doc->addPage();$doc->bookmark('Chapter 2', level: 0);$doc->setFont('helvetica', 'B', 18);$doc->cell(0, 12, 'Chapter 2', newLine: true);
$doc->save(getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/bookmarks.pdf');代码示例 — 生产环境
标题为“代码示例 — 生产环境”的章节下面是完整、可直接用于测试框架的示例。它会遵循 NEXTPDF_COOKBOOK_OUTPUT,并且自身不会引入任何不确定性。
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Bookmarks and Navigation');$doc->setPrintHeader(false);$doc->setPrintFooter(false);$doc->setAutoPageBreak(true, margin: 25);
// Chapter 1$doc->addPage();$doc->bookmark('Chapter 1: Introduction', level: 0);$doc->setFont('helvetica', 'B', 18);$doc->cell(0, 12, 'Chapter 1: Introduction', newLine: true);$doc->ln(3);
$doc->bookmark('What is NextPDF?', level: 1);$doc->setFont('helvetica', 'B', 14);$doc->cell(0, 10, 'What is NextPDF?', newLine: true);$doc->setFont('helvetica', '', 11);$doc->multiCell(0, 7, 'NextPDF is a modern PDF 2.0 library for PHP 8.4+. ' . 'It generates standards-targeting documents with typography, ' . 'graphics, and signatures.');$doc->ln(5);
$doc->bookmark('Key Features', level: 1);$doc->setFont('helvetica', 'B', 14);$doc->cell(0, 10, 'Key Features', newLine: true);$doc->setFont('helvetica', '', 11);$doc->multiCell(0, 7, 'HTML rendering, barcodes, PAdES signatures, ' . 'and a worker-safe architecture.');
// Chapter 2$doc->addPage();$doc->bookmark('Chapter 2: Getting Started', level: 0);$doc->setFont('helvetica', 'B', 18);$doc->cell(0, 12, 'Chapter 2: Getting Started', newLine: true);$doc->ln(3);
$doc->bookmark('Installation', level: 1);$doc->setFont('helvetica', 'B', 14);$doc->cell(0, 10, 'Installation', newLine: true);$doc->setFont('helvetica', '', 11);$doc->multiCell(0, 7, 'Install via Composer: composer require nextpdf/core');
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/bookmarks.pdf';$doc->save($out);
echo "Created bookmarks.pdf with a 2-level outline\n";边界情况与注意事项
标题为“边界情况与注意事项”的章节- 层级跳跃。 从层级 0 直接跳到层级 2,且中间没有层级 1,会在某些阅读器中呈现出结构看似错误的层级。每次最多只将层级增加一级。
- 在内容之前设置书签。 在你希望作为目标位置的地方调用
bookmark()。在大多数情况下,请把这个调用放在标题正前方。若把调用放在标题之后,目标位置会落在标题略下方。 - 以显式的 Y 值获得精确目标位置。 当
$y = -1时,目标位置即为当前光标的 Y 坐标。传入一个显式的 Y 值,可获得稳定的目标位置。举例来说,显式的 Y 值能固定一节的顶端,无论它前面有多少内容都不受影响。 - 大纲支持是普遍的,但呈现方式各异。 阅读器可能以折叠或展开状态渲染大纲。这个 API 无法强制每个项的展开或折叠状态。
每次 bookmark() 调用都会追加一个大纲项和一条目录条目,工作量为 O(1)。大纲树只会在 save() 时最终定型一次。数百个书签仍能轻松控制在 2000 ms / 64 MB 的预算内。
安全注意事项
标题为“安全注意事项”的章节书签标题会渲染到阅读器的导航界面中。如果标题包含用户可控的数据,请像处理任何将被显示的字符串一样,对其进行长度限制和净化。本示例不会执行任何输入解析,也不会进行任何网络访问。
符合性
标题为“符合性”的章节| 陈述 | 规范 | 条款 | 参考 ID |
|---|---|---|---|
| 文档大纲是一棵由大纲项组成的树,用作可视化目录。 | ISO 32000-2 | §12.3.3 | |
大纲项通过 Prev/Next 串接,并通过 First/Last 形成嵌套。 | ISO 32000-2 | §12.3.3 | |
大纲字典是 catalog 的 Outlines 项。 | ISO 32000-2 | §7.7.2 | |
| 目标位置可以与大纲项关联。 | ISO 32000-2 | §12.3.2 |
可重现性配置 — 结构层级。 trailer 的 /ID 和日期原子每次保存都会变动,因此测试框架会剥除这些原子,再比对经 qpdf 规范化后的结构。本示例说明 NextPDF 如何产生这样的结构。它并不作出全面符合 ISO 32000-2 的笼统声明。
商业情境
标题为“商业情境”的章节不适用。文档大纲和目录都是 Core 功能,没有 Premium 限制。