Long story short
With knp-snappy-bundle I can't generate a header in the PDF, while I can actually generate a footer.
Is it a bug, a feature, or I'm doing something wrong?
Details
1. Environment
I'm testing the knp-snappy-bundle, I've also installed the wkhtmltopdf binary from h4cc. This is part of my composer.json:
"h4cc/wkhtmltopdf-amd64": "^0.12.3",
"knplabs/knp-snappy-bundle": "^1.5",
The resulting binary of wkhtmltopdf says this:
$ vendor/bin/wkhtmltopdf-amd64 --version
wkhtmltopdf 0.12.3 (with patched qt)
2. Without headers or footers, it works
I've setup a controller that uses the knp-snappy-bundle and it works:
This is my PdfController:
public function downloadPdfAction( string $docName ) : Response
{
$pdf = $this->getPdf( $docName );
return new PdfResponse( $pdf, $this->getFilename( $docName ) );
}
private function getPdf( string $docName ) : string
{
$html = $this->renderView( 'AppBundle:documents:' . $docName . '.pdf.twig' );
$options = [];
$generator = $this->getPdfGenerator();
$pdf = $generator->getOutputFromHtml( $html, $options );
return $pdf;
}
private function getPdfGenerator() : Pdf
{
$generator = $this->get( 'knp_snappy.pdf' );
return $generator;
}
It basically:
- Has a
downloadPdfaction that- Gets a PDF document by its name, passed in as a parameter. In this example we'll use
'helloWorld'.
- Gets a PDF document by its name, passed in as a parameter. In this example we'll use
- Returns a new
Responsecreated with the content of the PDF, using thePdfResponseclass in the bundle.
- Returns a new
- To get the PDF
- it renders a view with the
twigengine.
- it renders a view with the
- gets the service (splitted into another function
getPdfGenerator()).
- gets the service (splitted into another function
- uses the service to
getOutputFromHtml()with no options passed-in.
- uses the service to
This is my helloWorld.pdf.twig:
<html>
<body>
<div class="pdfPageBody">
<h1>
Hello, World!
</h1>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
</body>
</html>
And here it is the resulting PDF, exactly as expected:
3. With headers and footers, it fails!
So I now add the header and footer. To do so, I just add a couple of twigs, render the HTMLs into a couple of variables, and pass them in into the options of the Pdf renderer:
private function getPdf( string $docName ) : string
{
$html = $this->renderView( 'AppBundle:documents:' . $docName . '.pdf.twig' );
$header = $this->renderView( 'AppBundle:documents:header.pdf.twig' );
$footer = $this->renderView( 'AppBundle:documents:footer.pdf.twig' );
$options = [
'header-html' => $header,
'footer-html' => $footer,
];
$generator = $this->getPdfGenerator();
$pdf = $generator->getOutputFromHtml( $html, $options );
return $pdf;
}
The header and footer are identical one to each other, except for the contained text:
This is my header.pdf.twig:
<html>
<body>
<div style="border: 5px dashed crimson; color: maroon; background-color: darksalmon">
This is a header
</div>
</body>
</html>
And the footer.pdf.twig:
<html>
<body>
<div style="border: 5px dashed crimson; color: maroon; background-color: darksalmon">
This is a footer
</div>
</body>
</html>
And wow!!! The footer gets rendered but the header does not!!
This is what I get:
To be noted in the image:
- There is "something" in the header. I can see the text of the page content like "clipped".
- The footer does not fully render, as it hides all the bottom border-lines, and the text base-line is aligned to the bottom edge of the page.
Soooo, hence my question!!
- What should I do to get the header rendered as well?
- Should'nt it be that I could see the header rendered in the PDF with this simple setup? Why does it not appear?


Solved!
Well, it seems that
wkhtmltopdfis really strict to consider the doctype and it does weird things if not.Inspired here: https://stackoverflow.com/a/28343079/1315009
So, I changed all the twigs to include
<!DOCTYPE html>:helloWorld.pdf.twig
header.pdf.twig
footer.pdf.twig
Final result
I finally got this:
It happens to have:
Hope to help!