Skip to content

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 ​

php
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']);
MethodReturns
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 ​

SettingDefaultWhat it does
pageblocks_pdf_paperA4paper size
pageblocks_pdf_fontDejaVu Sansdefault 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 @page and $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.

© PageBlocks 2019-present