NextPDF for CodeIgniter 4
At a glance
Section titled “At a glance”nextpdf/codeigniter connects the NextPDF Portable Document Format
(PDF) engine to a CodeIgniter 4 application through the framework’s
Services layer. You build PDF documents in controllers, jobs, or
commands, then return them as native CodeIgniter Hypertext Transfer
Protocol (HTTP) responses.
Install
Section titled “Install”composer require nextpdf/codeigniterThe package composer.json requires php >=8.4 <9.0,
nextpdf/core ^3.0 || ^5.2, and codeigniter4/framework ^4.6. It also
suggests nextpdf/artisan, nextpdf/premium, and codeigniter4/queue.
For the full requirements table, optional packages, and verification
steps, see /integrations/codeigniter/install/.
Conceptual overview
Section titled “Conceptual overview”NextPDF is a PHP 8.4 PDF 2.0 engine. The core engine
(nextpdf/core) is framework-agnostic. It does not know about HTTP,
routing, or dependency wiring. nextpdf/codeigniter is the adapter that
connects the engine to a CodeIgniter 4 application. With the adapter in
place, you do not wire registries, factories, or response handling
yourself.
The package adds four things to a CodeIgniter 4 application:
- A Services class (
NextPDF\CodeIgniter\Config\Services) that CodeIgniter discovers automatically. It exposes named services:fontRegistry,imageRegistry,documentFactory,pdfDocument,pdf,tsaClient, andpdfSigner. - A
Pdflibrary (NextPDF\CodeIgniter\Libraries\Pdf) — a high-level controller application programming interface (API). It wraps a single disposable document and turns it into a response in one call. - A
PdfResponsehelper (NextPDF\CodeIgniter\Http\PdfResponse) that creates a CodeIgniterDownloadResponsefor inline preview or download. It attaches a fixed set of response-hardening headers. - Two global helper functions,
pdf()andpdf_document(). They are registered through the Composerfilesautoload entry and the packageRegistrar.
The package also detects optional NextPDF extensions when it builds a
document. When nextpdf/artisan is installed and a Chrome binary is
configured, the document gets the Chrome renderer. When NextPDF Pro is
installed, PDF/A output and digital signing are available through the
same Services surface. Detection is conditional and silent. The package
never requires an extension that is not present.
Why a Services class and not a container binding
Section titled “Why a Services class and not a container binding”CodeIgniter 4 does not ship a PSR-11
dependency-injection container. Instead, it uses a Services locator. A
Services locator is a framework-discovered class with static factory
methods. Each method returns either a shared instance or a fresh one.
PSR-11 discourages the service-locator pattern — passing a container into
an object so the object can fetch its own dependencies — in PSR-11 §1.3
with the modal verb SHOULD NOT. The package follows CodeIgniter’s locator
convention. It also keeps the locator surface minimal and explicit: every
service is a named factory method with a bool $getShared parameter, and
callers receive concrete objects rather than a container handle.
This design keeps the CodeIgniter integration consistent with the Laravel and Symfony integrations. Each integration exposes the same logical services through its own framework’s idiom.
API surface
Section titled “API surface”| Entry point | Type | Returns | Lifetime |
|---|---|---|---|
Services::fontRegistry() | service | FontRegistryInterface | shared (warmed, then locked) |
Services::imageRegistry() | service | ImageRegistry | shared (bounded least recently used (LRU) cache) |
Services::documentFactory() | service | DocumentFactoryInterface | shared (stateless) |
Services::pdfDocument(false) | service | NextPDF\Core\Document | fresh per call |
Services::pdf(false) | service | NextPDF\CodeIgniter\Libraries\Pdf | fresh per call |
Services::tsaClient() | service | ?TsaClient | shared; null when no timestamp authority (TSA) URL |
Services::pdfSigner(false) | service | ?SignerInterface | fresh; null when signing disabled |
pdf() | helper | Pdf | fresh per call |
pdf_document() | helper | Document | fresh per call |
PdfResponse::inline() / download() | static | DownloadResponse | per call |
GeneratePdfJob | queue job | — | one per dispatch |
Code sample — Quick start
Section titled “Code sample — Quick start”A controller returns a PDF in three lines. Services::pdf() returns a
fresh Pdf library that wraps a fresh document. download() then
creates a CodeIgniter DownloadResponse.
<?php
declare(strict_types=1);
namespace App\Controllers;
use CodeIgniter\HTTP\DownloadResponse;use NextPDF\CodeIgniter\Config\Services;
final class InvoiceController extends BaseController{ public function download(int $id): DownloadResponse { $pdf = Services::pdf(); $pdf->document()->addPage(); $pdf->document()->cell(0, 10, "Invoice #{$id}");
return $pdf->download("invoice-{$id}.pdf"); }}The full runnable walkthrough is in /integrations/codeigniter/quickstart/.
It covers routing, inline preview, and the pdf() and pdf_document()
helper variations.
Code sample — Production
Section titled “Code sample — Production”In production, request a non-shared instance with Services::pdf(false).
Catch the single base exception, NextPDF\Exception\NextPdfException;
every core and extension failure extends it. Log the failure with context
instead of swallowing the error.
try { $pdf = Services::pdf(false); $pdf->document()->addPage(); $pdf->document()->cell(0, 10, "Invoice #{$id}");
return $pdf->download("invoice-{$id}.pdf");} catch (NextPdfException $e) { $logger->error('pdf.invoice.failed', [ 'invoice_id' => $id, 'exception' => $e::class, 'message' => $e->getMessage(), ]);
return $this->response ->setStatusCode(ResponseInterface::HTTP_INTERNAL_SERVER_ERROR) ->setJSON(['error' => 'pdf_generation_failed', 'invoice_id' => $id]);}The complete production controller is in /integrations/codeigniter/production-usage/. It adds observability timing, worker-safe lifetimes, and asynchronous generation.
Edge cases & gotchas
Section titled “Edge cases & gotchas”- The font and image registries are process-lifetime singletons. A
document is never shared.
pdfDocumentandpdfreturn a fresh instance on every call, so one request cannot leak content into another.Services::pdf(false)andpdf()both return a fresh library that wraps a fresh document. - The package requires the
mbstringandzlibPHP extensions. The font registry validates them once per process. If either extension is absent, the font registry raises a runtime error that names the missing extension. - Optional-extension behavior depends on what is installed in the same
application. With only
nextpdf/corepresent, the signing and PDF/A paths returnnullor are skipped. They never fail loudly.
Performance
Section titled “Performance”The integration adds no measurable overhead beyond the engine itself.
The font registry is parsed once and then locked. The image registry is
an LRU cache bounded by the imageCacheMb setting (50 MB by default).
The core engine and document content govern PDF build cost, not the
adapter. The per-page budget for this documentation set is 1500 ms wall /
128 MB peak. Real recipes set their own budget in front-matter.
Security notes
Section titled “Security notes”PdfResponse attaches a fixed set of response headers to every PDF it
emits: X-Content-Type-Options: nosniff, X-Frame-Options: DENY,
Content-Security-Policy: default-src 'none', X-Robots-Tag: noindex, nofollow, and Referrer-Policy: no-referrer. Filenames are sanitized,
and non-ASCII names are emitted with a Request for Comments (RFC) 5987
extended parameter. The queue job restricts builder callables to the
App\PdfBuilders namespace and confines output paths to
WRITEPATH/pdfs/. See /integrations/codeigniter/security-and-operations/
for the full threat model.
Conformance
Section titled “Conformance”- Module discovery relies on Composer’s PSR-4 autoloading. A namespace prefix maps to a base directory, and the fully qualified class name maps to a file path (PSR-4 §x1.x3).
- The Services design follows the locator guidance discussed under PSR-11 §1.3.
Commercial context
Section titled “Commercial context”NextPDF core is Apache-2.0. Digital signatures, PDF/A archiving, and
Factur-X e-invoice embedding are provided by NextPDF Pro and NextPDF
Enterprise. The CodeIgniter package exposes the corresponding service
methods. Those methods return null until the matching Premium package
is installed in the same application.
See also
Section titled “See also”- /integrations/codeigniter/install/ — install and verify the package.
- /integrations/codeigniter/quickstart/ — first PDF in a controller.
- /integrations/codeigniter/configuration/ — every configuration key.
- /integrations/codeigniter/boot-and-discovery/ — how CodeIgniter finds the Services class.
- /integrations/codeigniter/integration/ — wiring reference and smoke test.