PDF: documents from HTML
A contract, a certificate, a form, an invoice. Markup in, PDF out; the engine is dompdf, and it ships with the component.
This layer has no table and no migration: a document is built on the fly, and where to keep it is the calling code's business.
Printing
use Boshnik\PageBlocks\Support\Pdf;
// As bytes — into a mail attachment or a browser response.
$bytes = Pdf::view('file:docs/contract', ['order' => $order]);
// As a file on disk.
$file = Pdf::write(MODX_ASSETS_PATH . 'docs/42.pdf', $html);
// Landscape — portrait is no good for a waybill.
$bytes = Pdf::render($html, ['orientation' => 'landscape']);| Method | Returns |
|---|---|
available() | whether the engine is there |
render($html, $options) | PDF bytes, or null |
view($tpl, $data, $options) | the same, from a template |
write($path, $html, $options) | the path that was actually written |
$options: paper (A4, letter…), orientation (portrait / landscape), font.
The template in view() is resolved by the same resolver as view() everywhere else: a bare name is a chunk from the database, file: a file, file:<source>: a named source, @INLINE a template inline.
Why write() returns a path rather than true
Without dompdf an .html file is written instead, and calling that .pdf would be a lie. Take the extension from the returned path when you build a download name or an attachment name.
Empty markup is a refusal, not an empty document
On an empty string render() and write() return null and write to the log. An empty document is a broken template; handing over a blank sheet means handing it over for signature, and a white page no longer tells you there was nothing to print.
Settings
| Setting | Default | What it does |
|---|---|---|
pageblocks_pdf_paper | A4 | paper size |
pageblocks_pdf_font | DejaVu Sans | default font |
A font name the engine does not know silently falls back to Latin — changing it only makes sense for a font you have embedded yourself.
The default font is not decoration
With the built-in Helvetica, an invoice in Cyrillic reaches the signatory as a row of question marks, and it is the accountant who notices, not the developer. DejaVu ships with dompdf and covers Cyrillic and Romanian diacritics.
Orientation is a call option, not a setting
The document chooses it, not the site: an invoice is portrait, a waybill is landscape. One site-wide value would turn both the wrong way. Paper size is the opposite — it is about the country, not the document.
What has been decided for you
Remote addresses are not loaded
Remote loading is off and not exposed. A document is often built from what a visitor typed, and the flag turns <img src="http://10.0.0.1/..."> into a request the server makes.
The cost is stated plainly
An image at a remote address will not appear in the document. A logo on an invoice has to be a file, referenced by a path on disk.
File reads are chrooted to the site
The read root is MODX_BASE_PATH. Without it a path in the markup addresses the whole disk, and a template that someone else's string reached would read anything.
What is not there yet
- Headers, footers and page numbers. dompdf can do them through
@pageand$PAGE_NUM, but there is no wrapper for it. - A one-line browser response.
Response::download()takes a path, so the stream goes through a file that has already been written. By hand, as bytes:response($bytes, 200, ['Content-Type' => 'application/pdf']). - Merging and signing. Neither concatenating documents nor digital signatures.