CodeIgniter 包提供服务工厂、辅助函数,以及一个封装单个 Portable Document Format (PDF) 文档的轻量级 Pdf 库包装层。这个包装层适合在控制器中使用。队列任务使用静态构建器 callable,因为 CodeIgniter 的队列负载必须是可序列化数据。
当你围绕 nextpdf/codeigniter 设计控制器流程、服务、队列构建器或测试时,请使用本指南。
| 层 | 归属 | 职责 | 不要放在这里 |
|---|
| 控制器 | 应用程序 | 执行授权,调用构建器或服务,然后返回一个 DownloadResponse。 | 共享布局逻辑。 |
| 库包装层 | nextpdf/codeigniter | 封装一个 Document,并提供响应和保存辅助方法。 | 长生命周期的文档存储。 |
| 服务工厂 | nextpdf/codeigniter | 创建共享注册表和全新文档。 | 业务专属的存储根目录。 |
| 队列构建器 | 应用程序 | 基于静态 callable 输入构建一份文档。 | 请求对象或无法序列化的状态。 |
| 核心引擎 | nextpdf/nextpdf | 构建并序列化 PDF。 | CodeIgniter 响应或队列策略。 |
| 阶段 | 行为 | 开发者动作 |
|---|
| 自动加载注册 | Registrar::Autoload() 为该模块注册辅助函数加载。 | 通过 CodeIgniter 配置加载该模块。 |
| 服务解析 | Services::pdf() 默认返回一个封装全新文档的包装层。 | 每个请求只解析一次。 |
| 文档编写 | 应用代码通过 Pdf::document() 调用核心文档 API。 | 将文档构建代码放在服务或构建器中。 |
| 响应 | PdfResponse 返回一个 DownloadResponse。 | 让包设置 PDF 响应头。 |
| 队列执行 | GeneratePdfJob::process() 会验证构建器和输出路径,然后保存。 | 将队列构建器放在 App\PdfBuilders 下。 |
| 路径 | 用途 |
|---|
app/PdfBuilders/* | 可由 GeneratePdfJob 接受的静态、队列安全构建器。 |
app/Libraries/* | 围绕重复文档工作流的可选应用程序包装层。 |
app/Services/* | 领域数据检索与存储策略。 |
app/Config/NextPdf.php | 应用程序对包配置的覆盖。 |
tests/app/PdfBuilders/* | 构建器与队列负载测试。 |
短流程使用包提供的辅助函数即可。当文档构建逻辑属于某个需要直接测试的类时,请改用显式服务调用。
namespace App\Controllers;
final class InvoiceController extends BaseController
public function download(int $id)
->setTitle('Invoice ' . $id)
->writeHtml('<h1>Invoice ' . $id . '</h1>');
return $pdf->download('invoice-' . $id . '.pdf');
队列构建器应该是静态、具备确定性的,并位于 App\PdfBuilders 下。让 context 数组保持足够简单,便于序列化和审计。
namespace App\PdfBuilders;
use NextPDF\Core\Document;
final class InvoiceBuilder
public static function build(Document $document, array $context): Document
$document->setTitle((string) $context['title'])
->writeHtml((string) $context['html']);
这个作业会将输出限制在已配置的应用程序 PDF 目录内。如果你的应用程序需要租户专属存储,请将该策略放入一个单一服务,并在派发队列作业前先测试它。
| 扩展点 | 用于 | 限制 |
|---|
Services::pdfDocument() | 自定义文档创建方式。 | 必须返回一份全新文档。 |
Services::fontRegistry() | 字体预热和注册表访问。 | 拒绝不安全路径,并在预热后保持注册表锁定。 |
Services::pdfSigner() | 可选数字签名。 | 签名停用时返回 null。 |
NextPDF\CodeIgniter\Libraries\Pdf | 面向控制器的文档工作包装层。 | 一个包装层对应一份文档。 |
App\PdfBuilders::* | 队列安全的文档构建器。 | 必须是静态 callable 字符串。 |
app/Config/NextPdf.php | 应用程序默认值和集成设置。 | 保持生产环境取值明确。 |
- 先从调用
pdf() 或 service('pdf') 的控制器开始。
- 将重复的文档构建逻辑移入
app/PdfBuilders 或某个应用程序服务。
- 当请求路径上生成文档太慢时,请改用
GeneratePdfJob。
- 保持队列 context 可序列化且精简。
- 除非你有意扩展策略,否则请将输出存放在批准的 PDF 存储根目录下。
- 为辅助函数、服务、队列负载和不安全路径添加测试。
| 失败情况 | 应该在哪里处理 | 建议的回应方式 |
|---|
| 缺少扩展或字体路径不安全 | 服务工厂。 | 在服务解析期间快速失败(fail fast)。 |
| 无效的构建器 callable | 队列作业验证。 | 拒绝该作业,并在不泄露机密的情况下记录构建器字符串。 |
| 不安全的输出路径 | 存储服务与队列作业。 | 派发前拒绝,并保留作业验证。 |
| 响应序列化错误 | 控制器或框架错误处理。 | 不要发送不完整的响应正文。 |
| 可选 Premium 类不可用 | 服务方法返回值。 | 在使用可选电子发票功能前,先明确处理 null。 |
| 关注项目 | 默认值 | 何时该覆写 |
|---|
| 队列构建器命名空间 | App\PdfBuilders。 | 除非你也同步更新安全策略,否则保留默认值。 |
| 输出根目录 | WRITEPATH/pdfs。 | 只有在采用更严格的允许列表时才覆盖。 |
| 响应文件名 | document.pdf。 | 使用经过清理的业务文件名。 |
| 流式传输方法 | 与其他框架保持 API 一致。 | 在 CodeIgniter 中,不要依赖流式传输来充当内存边界。 |
| 文档服务 | 默认全新。 | 不要在请求代码中请求共享文档。 |
- 服务测试会断言每次
Services::pdf() 解析都返回独立文档。
- 辅助函数测试会断言
pdf() 与 pdf_document() 都返回全新对象。
- 响应测试会断言响应头与文件名规范化。
- 队列测试会涵盖无效的构建器字符串与不安全的输出路径。
- 构建器测试会使用具有代表性的 context 数据。
- 配置测试会涵盖字体路径、缓存路径、签名停用,以及 Time-Stamp Authority (TSA) 停用等状态。