Here is our answer:
We are currently using wkhtmltopdf to generate a PDF from a given html template.
Some background information:
We are using Sulu CMF to build our back end, which is based on Symfony2. The KnpSnappy Bundle is used as a Symfony wrapper for wkhtmltopdf.
How we generate PDFs:
As many PDFs share the same header and footer we have created a BasePDFBundle which offers a PDFManager to build the PDF on the fly by a given TWIG template. Per default a generic header and footer (usually with the customer's name and logo) is included.
The footer Problem / Page numbers in the footer (or header):
It is very useful to add page numbers to a PDFs eg. for orders, however most of our content is added dynamically (eg a product list). As the styling of the PDF can change and the content itself is dynamically added there had to be a quick and easy way to add the current and the total page to the generated PDF. Here is what we did:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<base href="{{ app.request.schemeAndHttpHost }}" />
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link rel="stylesheet" href="{{ asset('bundles/pdfbase/css/pdfstyles.css') }}"/>
</head>
<body class="footer">
<div class="footer-container">
<div class="footer-widget">
<b>FooBar Company Name</b>
</div>
<div class="text-align-right">
<span class="page"></span>/<span class="topage"></span>
</div>
</div>
<script type="text/javascript">
(function() {
// get all url parameters and transform it to a list
// pdf generator adds a param for current and the total page sum
// add the value to the html elements
var urlParams = document.location.search.substring(1).split('&');
var urlParamsList = {};
var pagingElements = ['topage', 'page'];
for (var i in urlParams) {
var param = urlParams[i].split('=', 2);
urlParamsList[param[0]] = unescape(param[1]);
}
for (var i in pagingElements) {
var elem = document.getElementsByClassName(pagingElements[i]);
for (var j = 0; j < elem.length; ++j) {
elem[j].textContent = urlParamsList[pagingElements[i]];
}
}
})();
</script>
</body>
Yes the variable names of page
and topage
could be better, however they are the same as the KnpSnappy wrapper uses when merging twig templates to the final PDF template. This is the easiest way to get the current and total page number because you can let the wrapper do all the calculations.
In the end you simply have to replace the text of html tags and thats it!
Differences between your local machine and server:
As wkhtmltopdf opens a virtual browser to "render" the twig templates this could lead to errors in your pdf generation on your server. We found out it is not a good idea to use event tags like <body onload="doSomething()">
you rather should trigger your javascript code like we did it in the example above.
onload="doSomething"
. All the examples I've seen were using that approach and it didn't work. This does. Thanks! – codemonkey