Er zijn verschillende html naar PDF converters beschikbaar onder Php. Een van de betere die op dit moment beschikbaar is, is 'spipu/html2pf'. Indien de html vooraf redelijk vast staat en gegenereerd wordt vanuit eigen templates is deze library goed te gebruiken. Zelf liep ik er tegen aan de wens was om PDF-bestanden te genereren op basis van ontvangen e-mails. Het probleem met pdf-genereer-libraries is dat deze met regelmaat html niet juist herkende en daardoor Php-fouten genereren en/of onjuiste html.
Na wat zoeken vond ik wkhtmltopdf. Dit is geen library, maar een command-line tool op basis van WebKit - de core van Google's Chrome - dat PDF-bestanden genereert met html. Binaries zijn zowel beschikbaar voor Linux als Windows. Voor Linux zit het zelfs in de meeste distributies als standaard package!
Om dit in Php te gebruiken kan dit natuurlijk direct worden aangeroepen, maar het is mooier om een zogeheten 'wrapper'-function hiervoor te maken. Het uit te voeren commando voor het converteren van html naar PDF is: wkhtmltopdf <file.html> <output.pdf>
Nu is het mogelijk 2 temp-bestanden te genereren, 1 met de html en 1 met de output van de PDF, maar het is natuurlijk nog mooier als dit niet hoeft. Om te begrijpen hoe dit mogelijk is, is technische achtergrond nodig hoe input/output van command-line processen verlopen. Elk proces leest eventuele invoer vanuit 'stdin', standaard is dit getype text. Stdout en stderr zijn 2 aparte streams die output tonen, wat standaard getoond wordt in de Command-prompt/shell.
Nu is het mogelijk om ipv een bestandsnaam een '-' op te geven. Het commando "wkhtmltopdf - output.pdf" verwacht z'n invoer nu vanuit 'stdin' en stuurt de uitvoer naar output.pdf. Als je wilt dat de uitvoer naar stdout gaat, kan hier ook een '-' worden opgegeven: 'wkhtmltopdf - -".
Met deze kennis kan vervolgens een functie gemaakt worden:
function html2pdf($html) {
$pipes = array();
$ds = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
// 2 => array("file", "stderr.txt", "a")
);
$stdout = null;
$p = proc_open("wkhtmltopdf - -", $ds, $pipes);
if (is_resource($p)) {
fwrite($pipes[0], $html);
fclose($pipes[0]);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
}
$return_value = proc_close($p);
// return's pdf-data
return $stdout;
}
Dit script start het proces 'wkhtmltopdf' en schrijft vervolgens de html er naar toe en sluit pipes[0], 'stdin'. Op dit moment weet het proces dat het alle html heeft gelezen, genereert de pdf en geeft deze terug als uitvoer.