
Suivez ce tutoriel et découvrez comment générer facilement des documents PDF avec Symfony2.
Pour commencer, partons du besoin : générer des documents pdf dans un projet Symfony 2. Pour savoir quel package utiliser nous allons faire une petite recherche. Dans ce domaine, Google c’est bien mais ça ne vaut pas packagist qui est fait pour ça.

Recherche du terme « pdf » sur packagist.org
Comme vous le voyez sur la capture ci-dessus, 2 packages sortent du lot : dompdf et knp-snappy. J’ai choisi dompdf pour 2 raisons : il a quand même 50% d’étoiles en plus sur le site et knp-snappy utilise wkhtmltopdf qui est excellent mais peut être un cauchemar à mettre en place, alors que dompdf n’utilise aucune dépendance de ce type.
Installation du bundle dompdf
Passons maintenant aux choses sérieuse. Comme tout package supporté par Composer, l’installation de dompdf est ultra simple :
composer require dompdf/dompdf
Installer dompdf avec Composer

composer require dompdf/dompdf
Si les pré-requis sont remplis, tout se fait tout seul. A propos des pré-requis, ils sont assez nombreux, mais assez courants :
- PHP version 5.3.0 ou supérieur
- DOM extension
- GD extension
- MBString extension
- php-font-lib
- php-svg-lib
Il est aussi possible de mettre en place un OPcache (OPcache, XCache, APC…) et/ou les extensions IMagick ou GMagick pour améliorer les performances. Pour plus de détails rendez-vous ici.
Tout s’est bien passé ? Vous n’avez plus rien à faire, même pas besoin de modifier votre fichier AppKernel.php.

Exemple simple : hello world
Allons-y doucement et commençons par un exemple tout simple : nous allons afficher une simple chaîne de caractères dans un document A4 tout blanc. Simple comme bonjour.
<?php
// On importe la classe Dompdf
use Dompdf\Dompdf;
//...
class TestController extends Controller
{
public function toPdfAction() {
// On crée une instance de Dompdf
$dompdf = new Dompdf();
// On ajoute le texte à afficher
$dompdf->loadHtml('Hello world');
// On fait générer le pdf à Dompdf ...
$dompdf->render();
// et on l'affiche dans un objet Response
return new Response ($dompdf->stream());
}
// ...
Génération d'un fichier pdf simple avec Symfony2 et dompdf
Je pense que les commentaires du code parlent d’eux-même. Nous allons pouvoir passer aux choses sérieuses et attaquer un exemple réel

Exemple réel : un pdf à partir d’un template twig
Afficher un texte noir sur fond blanc c’est un bon début mais ça ne sert pas à grand chose. Maintenant nous allons générer un pdf avec un en-tête et un pied de page et nous allons y afficher les détails d’un objet.
Premièrement, occupons-nous du contrôleur :
<?php
// On inclue dompdf et la classe qui permet de gérer ses options
use Dompdf\Options;
use Dompdf\Dompdf;
//...
class ObjectController extends Controller
{
public function toPdfAction($objectId) {
// On récupère l'objet à afficher (rien d'inconnu jusque là)
$objectsRepository = $this->getDoctrine()->getRepository('TestBundle:Object');
$object = $objectsRepository->findOneById($objectId);
// On crée une instance pour définir les options de notre fichier pdf
$options = new Options();
// Pour simplifier l'affichage des images, on autorise dompdf à utiliser
// des url pour les nom de fichier
$options->set('isRemoteEnabled', TRUE);
// On crée une instance de dompdf avec les options définies
$dompdf = new Dompdf($options);
// On demande à Symfony de générer le code html correspondant à
// notre template, et on stocke ce code dans une variable
$html = $this->renderView(
'TestBundle:Object:pdfTemplate.html.twig',
array('object' => $object)
);
// On envoie le code html à notre instance de dompdf
$dompdf->loadHtml($html);
// On demande à dompdf de générer le pdf
$dompdf->render();
// On renvoie le flux du fichier pdf dans une Response pour l'utilisateur
return new Response ($dompdf->stream());
}
Exemple de controleur Symfony2 permettant de générer un pdf à partir d'un template
Ensuite, voyons un exemple de template qui peut être utilisé :
<html>
<head>
<style>
/* On commence par définir les propriétés de la page : les marges en haut
* et en bas permettront d'insérer un en-tête et un pied de page */
@page {
margin: 50px 0 25px 0;
}
/* La position fixed permet de placer les éléments sur toutes les pages
* du document pdf, le reste n'est que décoration */
#header, #footer {
position: fixed;
left: 0px;
right: 0px;
color: #fff;
background-color: #000;
}
#header {
top: -50px;
height: 50px;
}
#footer {
bottom: -25px;
height: 25px;
}
/* Pour améliorer un peu la lisibilité on ajoute une marge au corps de
* texte. Ca aurait pu être fait en agrandissant les marges au niveau
* de la page mais je trouve qu'utiliser un div dédié pour le contenu
* est cohérent */
#content {
margin: 25px;
}
/* On teste quelques d'options css différentes */
h1 { text-transform: uppercase; text-align: center; font-weight: bold}
h2 {font-style: italic; font-weight: bold; border: solid 1px #ccc; }
/* On met même en place un système de colonnes pour tester les float */
.col-25, .col-75 { float: left; }
.col-25 { width: 25%; }
.col-75 { width: 75%; }
.row { clear: both; }
</style>
</head>
<body>
<!-- On commence par ajouter le header et le footer pour qu'ils soient
visibles sur toutes les pages. Si on les ajoute après avoir rempli plus
d'une page, ils ne seront insérés qu'après le saut de page -->
<div id="header">
<!-- Grâce aux options définies dans le contrôleur on peut insérer des
images à partir de leur url absolue -->
<img src="{{ app.request.getSchemeAndHttpHost() ~ asset('/bundles/test/img/logo.png') }}" alt="logo">
</div>
<div id="footer">Texte du footer</div>
<!-- Maintenant on rempli le document -->
<div id="content">
<h1>{{object.title}}</h1>
<h2>{{object.subtitle}}</h2>
{% for prop in object.properties %}
<div class="row">
<div class="col-25"><h3>{{prop.name}}</h3></div>
<div class="col-75">{{prop.value}}</div>
</div>
{% endfor %}
</div>
</body>
</html>
Exemple de template twig permettant de générer un document pdf

Que retenir de tout ceci ?
Un petit exemple vaut plus qu’un long discours et je suis persuadé que c’est le cas ici. Vous voyez que c’est à peu près aussi simple de générer un fichier pdf que d’envoyer un email avec SwiftMailer. Vous voyez aussi que contrairement à d’autres outils, dompdf supporte des propriétés css assez sympa. En fait, quasiment toutes les propriétés css 2.1 sont supportées et, même si la doc indique que les float peuvent produire un résultat différent de celui attendu, j’ai voulu les inclure dans mon exemple pour vous montrer que si on reste raisonnable le résultat est plus que correct. Finalement il ne vous reste plus qu’à implémenter vos propres codes pour vous faire votre propre avis… et à venir le partager dans les commentaires ci-dessous.
Si vous avez aimé cet article, vous aimerez peut-être
Source : dompdf sur Github