Chapters
31 Chapters
|
3:19:40
|
Login to bookmark this video
-
Course Code
Subscribe to download the code!Compatible PHP versions: ^7.1.3
Subscribe to download the code!Compatible PHP versions: ^7.1.3
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
15.
PDF: Snappy, wkhtmltopdf & Template Setup
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
Subscribe to jump to this part in the video!
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
This tutorial is built on Symfony 4.3, but will work well with Symfony 4.4 or 5.
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": "^7.1.3",
"ext-iconv": "*",
"aws/aws-sdk-php": "^3.87", // 3.110.11
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"doctrine/annotations": "^1.0", // 1.10.1
"doctrine/doctrine-bundle": "^1.6.10", // 1.11.2
"doctrine/doctrine-migrations-bundle": "^1.3|^2.0", // v2.0.0
"doctrine/orm": "^2.5.11", // v2.7.2
"knplabs/knp-markdown-bundle": "^1.7", // 1.7.1
"knplabs/knp-paginator-bundle": "^2.7", // v2.8.0
"knplabs/knp-snappy-bundle": "^1.6", // v1.6.0
"knplabs/knp-time-bundle": "^1.8", // v1.9.1
"league/flysystem-aws-s3-v3": "^1.0", // 1.0.23
"league/flysystem-cached-adapter": "^1.0", // 1.0.9
"league/html-to-markdown": "^4.8", // 4.8.2
"liip/imagine-bundle": "^2.1", // 2.1.0
"nexylan/slack-bundle": "^2.1,<2.2.0", // v2.1.0
"oneup/flysystem-bundle": "^3.0", // 3.1.0
"php-http/guzzle6-adapter": "^1.1", // v1.1.1
"phpdocumentor/reflection-docblock": "^3.0|^4.0", // 4.3.1
"sensio/framework-extra-bundle": "^5.1", // v5.4.1
"stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
"symfony/asset": "^4.0", // v4.3.4
"symfony/console": "^4.0", // v4.3.4
"symfony/flex": "^1.9", // v1.21.6
"symfony/form": "^4.0", // v4.3.4
"symfony/framework-bundle": "^4.0", // v4.3.4
"symfony/mailer": "4.3.*", // v4.3.4
"symfony/messenger": "4.3.*", // v4.3.4
"symfony/property-access": "4.3.*", // v4.3.4
"symfony/property-info": "4.3.*", // v4.3.4
"symfony/security-bundle": "^4.0", // v4.3.4
"symfony/sendgrid-mailer": "4.3.*", // v4.3.4
"symfony/serializer": "4.3.*", // v4.3.4
"symfony/twig-bundle": "^4.0", // v4.3.4
"symfony/validator": "^4.0", // v4.3.4
"symfony/web-server-bundle": "^4.0", // v4.3.4
"symfony/webpack-encore-bundle": "^1.4", // v1.6.2
"symfony/yaml": "^4.0", // v4.3.4
"twig/cssinliner-extra": "^2.12", // v2.12.0
"twig/extensions": "^1.5", // v1.5.4
"twig/extra-bundle": "^2.12|^3.0", // v2.12.1
"twig/inky-extra": "^2.12", // v2.12.0
"twig/twig": "^2.12|^3.0" // v2.13.1
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0", // 3.2.2
"easycorp/easy-log-handler": "^1.0.2", // v1.0.7
"fzaninotto/faker": "^1.7", // v1.8.0
"symfony/browser-kit": "4.3.*", // v4.3.5
"symfony/debug-bundle": "^3.3|^4.0", // v4.3.4
"symfony/dotenv": "^4.0", // v4.3.4
"symfony/maker-bundle": "^1.0", // v1.13.0
"symfony/monolog-bundle": "^3.0", // v3.4.0
"symfony/phpunit-bridge": "^3.3|^4.0", // v4.3.4
"symfony/stopwatch": "4.3.*", // v4.3.4
"symfony/var-dumper": "^3.3|^4.0", // v4.3.4
"symfony/web-profiler-bundle": "4.3.*" // v4.3.4
}
}
24 Comments
Though using wkhtmltopdf, was for me, a useful tool at the time, it certainly isn't perfect and can cause issue with complicated HTML/CSS. I do not use wkhtmltopdf anymore and it's very rare for a release to occur. This was one of the main reasons I dropped use of it, as there are some fixes in the alpha version that would have resolve some issues, but has been in alpha for over 2-3 years. Plus, it's trying re-invent the wheel with a browser.
An even more useful tutorial would be to use Puppeteer and Chromium to render the page "exactly" as it would look in a browser.
For a less complicated option, MPDF would also be a good choice, though you have to be careful with the CSS - but perfectly easy to manage this.
I'd be happy to share my experiences with Puppeteer and Chromium and a solid way of managing these dependencies for a project.
Yo Kevin S.!
Yea, it's SO true that their releases are a mess these days and we've had compatibility issues getting it installed in certain systems :/. We haven't had many problems with the rendering - though we have had a few minor issues.
> For a less complicated option, MPDF would also be a good choice, though you have to be careful with the CSS - but perfectly easy to manage this
What do you mean by "have to be careful with the CSS"?
> I'd be happy to share my experiences with Puppeteer and Chromium and a solid way of managing these dependencies for a project
Sure! I'd love to hear about this - it looks like it's a Node library and you can write a pretty small script that would do, basically something similar to wkhtmltopdf?
Cheers!
Hi!
MPDF does support CSS, but you'll find what your design for a modern browser, the results from MPDF aren't the same and can be wildly different. It's possible to resolve these by fiddling with the CSS. Just depends on your project and having to keep a set of additional CSS styles just for PDF generation.
With node, you can install Puppeteer (which comes with Chromium) and you use a simple Node JS script to call a URL and then convert it to PDF.
The reason I'm quite passionate about this subject is, that I was solely working on a project (6 years old now) that did the following;
* Used wkthmltopdf to render SPA app and hit many issues with rendering, was never perfect and was prone to issues on attempting to wait for the JS to finish rendering
* Used Firefox in headless mode, which requires the use of X Server to do it and that can be a world of pain and it's not always reliable. Maintenance hell and really a security risk having this on a webserver.
About 2 months ago, I rewrote the whole PDF processor as a microservice, using Symfony 4 and Puppeteer and the results produced were perfect, as well as being a lot faster and not needing to run X Server. Also, the set-up is much more secure, as the service can only be called from within our internal network - a much better set-up.
You do need to install gtk3 and libXScrnSaver from your OS packager manager (yum for example) and that's it - much easier to manage packages than having to manage installing a binary.
I can put together a simple working Symfony project to get you up and running, and perhaps, with your pizzazz, you can turn it into an "awesome" tutorial for the SymfonyCasts community ? :)
There is also https://weasyprint.org/ . It does not support forms and JavaScript but looks promising.
Hmm, that's a good one. And maybe https://pdflayer.com/ if you want something as a paid-service? I haven't used it yet - but having this HTML->PDF generation as a service... would be nice for lazy people like me ;)
pdflayer seems to use wkthmltopdf under the hood. :) It generates files with creator property set to qt. qt is toolkit library used for GUI application aaaand used by wkhtmltopdf to generate pdfs. :)
Right now is better to use WeasyPrint: https://blog.theodo.com/2023/11/pdf-generation-weasyprint-symfony/
The wkhtmltopdf package is outdated, has security vulnerabilities, and is not available in the Alpine distribution.
Hey Jared,
Thanks for this tip! Indeed, Wkhtmltopdf is outdated lately, sad to see it does not have much attention from the maintainers. I have not tried WeasyPrint myself, but seems like a popular replacement.
Cheers!
Yeah, it has the same api like wkhtmltopdf. I just tested it, everything works like a charm.
Hey Jared,
That sounds cool! Thanks for confirming it :)
Cheers!
Hey Ryan, the
encore_entry_link_tags()doesn't (or no longer) work... It generates an absolute BROWSER path, meaning it starts from the public folder as root, like the page is served to the browser. But WKHTMLTOPDF is not actually served from the browser, so the paths need to be absolute to your filesystem.Am I missing some extra configuration you did for this or did it maybe break over time? (considering we are quite a few versions of ahead since the making of this article)
Hey @ChrisV!
Hmm. Actually, iirc, the absolute paths are exactly what you want. Behind the scenes, wkhtmltopdf renders the HTML like a web page, including grabbing any external JS, CSS or images.
Btw, another option is to inline all the JS and CSS - e.g. by using
inline_css()or writing a quick Twig extension that loads all of the CSS & JS files you need and returns their contents as a string (so you can dump them intoscriptandlinktags). Then no external requests to CSS or JS would be needed.Cheers!
Well yes, absolute paths are what I want/need, but absolute to the filesystem, not the browser path (the URI bit). But since WKHTMLTOPDF is not rendering inside a browser, it won't find the css files correctly. If I simple do
encore_entry_link_tags(), my css doesn't work because the paths are not found.Therefore I did indeed already add all the css inline, but i'm running into problems with fonts.
We use Google Fonts, but loading them externally is often resulting in connection problems. Who knows why, maybe a ratelimit of some sorts. So I'm trying to include the ttf font in the assets bundle. But this won't work in WKHTMLTOPDF because the all the paths are relative to the public dir (absolute to the URL). This means the font files can not be found. Making the path hardcoded absolute doesn't work either because DEV / TEST / PROD environment all have different filesystems...
The only other alternative is to base64-encode the font en include them hardcoded in the inline css, but that seems quite dirty...
Hey Chris!
I've noticed that wkhtmltopdf can sometimes be "finicky" with external files also. It works some times, but not all the times.
To be honest, I'm not sure :/. We do "inline" the CSS for our PDFs like we've been discussing. But we haven't had any problems with the fonts. I would say that I don't have any practical problem with embedding the fonts as base64 - that might be a nice workaround. We're effectively doing that already for the CSS by inlining it, so why not also make sure that the fonts are entirely "inside" of the source. It seems ok if it gets this working. PDF's are such a pain to deal with.
Cheers!
I infer from some of these comments that this tutorial is kind of dated, and I should probaby look elsewhere for a PDF generation library for my Symfony 6 project. Just wondering if anyone has any recent/new suggestions. Do you still like https://github.com/dompdf/d... I'm planning to give it a try.
Hey davidmintz!
I haven't had a chance to use DomPDF yet but I believe that it IS the way forward - so definitely try it :).
Cheers!
Hello,
Since we migrated from symfony 4 to 5, all my PDFs generated with snappy and wkhtmltopdf are "zoomed off" by around 25%, leaving a padding on the right and on the bottom of each page.
Have you ever experienced that ?
I do not reproduce with wkhtmltopdf 0.12.5 but the binary is now only available on 0.12.6 and it doesn't work with this version on my server.
And i am usign KnpSnappy 1.9
I tried to find a solution on the internet but without success...
Hey Pascal!
Hmm. I have not experienced this. But this is the pain of wkhtmltopdf: the version of the binary are super tricky to get correct in each environment :/. If you have enough problems, I'd recommend trying: https://github.com/dompdf/d.... In general, I think wkhtmltopdf is (and has been for awhile) kind of dead. And (finally) some new solutions are being proposed.
Cheres!
Hello
i use knpSnappy
I wanted to know if it was possible to recover content to generate in JS in the TWIG and then generate a pdf
Currently, I cannot retrieve my js :
`
...
S1 :
S2:
S3:
What is the right approach knowing that I am generating charts.
Is it possible ?
Thanks
Hi Kehlhoffner E.!
Hmm. You mentioned:
> Currently, I cannot retrieve my js
Do you know the nature of the problem? Are the script tags generating with the wrong path? Are they not generating at all? Let me know, and I'll do my best to offer some advice :)
Cheers!
Hi there!
composer require knplabs/knp-snappy-bundleoutputs this message:
`Problem 1
:)
Brs.
Hey
Are you trying to install KnpSnappyBundle on Symfony 5? Or what version of Symfony do you have? Because looks like it is not ready for Symfony 5 yet as you can see from composer.json: https://github.com/KnpLabs/... though there's a PR for this: https://github.com/KnpLabs/...
Cheers!
Hi there!
I am using
"extra": {
"symfony": {
"allow-contrib": false,
"require": "4.4.*"
}
}
Best regards.
Hey AbelardoLG,
Hm, what version of "symfony/framework-bundle" do you have installed? You can check it with:
$ composer info symfony/framework-bundle
Or you don't have this framework bundle at all? Try to upgrade this first, because from the output I see knplabs/knp-snappy-bundle v1.6.0 requires symfony/framework-bundle ~2.7|~3.0|^4.0 and your "4.4.*" you have in extra should fit the "^4.0" pattern.
Cheers!
"Houston: no signs of life"
Start the conversation!