skip to main | skip to sidebar
Code 18
Manuel du savoir-faire à l'usage des geeks et des curieux
RSS
  • Accueil
  • Le web au Québec
  • Liens
  • Twitter
  • Facebook
  • À propos

vendredi 17 septembre 2010

Générer un PDF en PHP

Publié par Infinite Loop, à 20 h 42 1 commentaire

Est-ce qu'un client vous a déjà demandé de générer un PDF par PHP alors que vous n'aviez pas sous la main la librairie FPDF ou PDFlib (lite ou la licence commerciale à 1000$ pour serveur) ? Parfois, les moyens sont limités mais on doit quand même livrer quelque chose de fonctionnel, que ce soit pour générer un reçu ou une facture autrement que par HTML.

À quelques reprises, je me suis servi d'un petit script gratuit nommé DOMpdf qui s'est avéré suffisant pour mes besoins. Ce package est constitué d'un ensemble de script PHP pour générer des PDF de base à partir d'une simple structure de document HTML (d'où son nom DOM). Il supporte l'inclusion d'images et tente du mieux possible de suivre les règles CSS.

Il ne faut pas s'attendre à la perfection alors je recommande de construire son gabarit HTML le plus simplement possible pour éviter les mauvaises surprises. Pour ma part, j'ai pu mettre sans effort une image d'entête (logo), des tableaux et un peu de CSS pour la mise en page (beaucoup de règles ne sont pas supportées). Le résultat est assez fidèle aux attentes du client.

Comme il ne nécessite aucune installation d'extension sur le serveur, il suffit de télécharger le fichier compressé et de le dézipper dans le répertoire de son projet. J'ai utilisé la version stable 0.5.1 disponible sur Google Code, la version 0.6 étant encore en beta (depuis mai 2010).

Ce que je voulais arriver à faire, c'était de personnaliser un gabarit HTML en utilisant des substitutions (identifiées par des balises de commentaires), générer un PDF automatiquement sans même à avoir à le stocker sur disque et l'envoyer en attachement par courriel.

Pour ce faire, DomPDF m'a permis de convertir le document HTML en format PDF et le composant Zend_Mail de Zend Framework a été pratique car il possède la capacité de créer un attachement de fichier à partir de son contenu binaire et de l'envoyer par email.

Quelques lignes de code PHP ont suffi pour arriver à mes fins et c'est étonnamment assez performant (1 page générée à la volée - temps d'exécution pratiquement instantané) :

# Étape 1
require_once('Zend/Mail.php');
require_once('dompdf-0.5.1/dompdf_config.inc.php');

# Étape 2
$html = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/template.htm');
$html = str_replace('<!-- name -->', 'Code 18', $html);
// autres substitutions...

# Étape 3
$dompdf = new DOMPDF();
$dompdf->load_html($html);

# Étape 4
$dompdf->render();

# Étape 5
// si on veut le faire afficher en attachement "save as"
// $dompdf->stream('nom-du-document.pdf');

$pdfBinary = $dompdf->output();

# Étape 6
$mail = new Zend_Mail('UTF-8');

// propriétés
$mail->setFrom('code18.blogspot@gmail.com');
$mail->addTo('code18.blogspot@gmail.com');
$mail->setSubject('Document PDF');
$mail->setBodyText('Voici votre document PDF personnalisé');

# Étape 7 : créer l'attachement
$file = $mail->createAttachment($pdfBinary);
$file->type = 'application/pdf';
$file->disposition = Zend_Mime::DISPOSITION_ATTACHMENT;
$file->filename = 'nom-du-document.pdf';

// envoyer le message
$mail->send();
Explications par étapes :
  1. J'inclus d'abord les deux librairies. C'est bel et bien le fichier dompdf_config.inc.php qu'on doit inclure et non dompdf.php. Curieux mais c'est comme ça.
  2. Je lis la source HTML du gabarit et j'effectue les remplacements.
  3. Je crée un objet DOMPDF et je lui passe la variable qui contient le contenu HTML en utilisant la fonction load_html(). D'autres configurations peuvent être faites ici, comme par exemple indiquer le chemin de base des images ou d'une feuille de style externe (avec set_base_path).
  4. Appeler la méthode render() est obligatoire. À ce stade-ci, le PDF est généré en mémoire seulement.
  5. Pour récupérer le fichier PDF, on peut utiliser stream() pour l'envoyer à l'utilisateur (sous forme de fenêtre "Enregistrer sous") ou encore, comme c'est le cas pour moi, récupérer le contenu binaire du fichier en appelant la fonction output().
  6. J'instancie un objet Zend_Mail pour construire le email à envoyer.
  7. Je crée un fichier en attachement en passant en paramètre la variable contenant le binaire du PDF, qui sera automatiquement lié à l'objet $mail par l'appel à createAttachment().
Un peu plus de fonctionnalités
Les capacités de DOMpdf sont assez rudimentaires. On pourrait compléter le traitement et la manipulation à l'aide d'autres outils. Par exemple, une fois le PDF généré, s'il était enregistré sur le disque du serveur, on pourrait appeler des fonctions de PDFtk (toolkit), un outil gratuit et polyvalent, accessible à partir du shell (shell_exec en PHP) qui permettra de fusionner le PDF nouvellement créé à un autre document PDF, l'encrypter contre l'édition (avec un mot de passe), appliquer un filigrane ou un arrière-plan, etc.


Tags: PHP, Programmation, Zend Framework

1 réponse à "Générer un PDF en PHP"

  1. Cybeber a dit...
    4 novembre 2011 à 19 h 05

    Excellent article, très clair et facile à mettre en oeuvre.
    En revanche, je ne parviens toujours pas à insérer une image (dompdf m’intègre le contenu du fichier public/index.php, alors que le .htaccess est bien configuré) ni de header ou footer, malgré de multiples tentatives.
    En tout cas, déjà merci pour ce sympathique tuto.


Publier un commentaire

Message plus récent Messages plus anciens Accueil
S'abonner à : Publier des commentaires (Atom)
    Suivre @code18 sur Twitter

    Catégories

    • Apache (21)
    • Citations (167)
    • Club Vidéo (24)
    • Coffre à outils (56)
    • CSS (8)
    • Curiosités (117)
    • Design Pattern (2)
    • Drupal (8)
    • Easter Eggs (22)
    • Extensions Firefox (20)
    • GIMP (7)
    • Histoire (21)
    • HTML (32)
    • Humour (57)
    • Intégration (34)
    • iPod (12)
    • JavaScript (110)
    • Jeu de combat (6)
    • Le coin du geek (128)
    • Liens (12)
    • Linux (56)
    • Livres (78)
    • Lois et principes (46)
    • Marché des saveurs (26)
    • Mathématique (18)
    • Mobile (5)
    • Montréal (32)
    • Musique (112)
    • Pancartes et écriteaux (16)
    • Perl (8)
    • Pérou (1)
    • PHP (130)
    • PostgreSQL (44)
    • Programmation (105)
    • Saviez-vous que (55)
    • Sécurité (22)
    • SEO (5)
    • SQL Server (22)
    • Vieilles publicités (6)
    • Virtualisation (8)
    • Voyages (1)
    • Zend Framework (26)

    Divers

    Archives

    • ►  2015 (6)
      • ►  août 2015 (1)
      • ►  juillet 2015 (1)
      • ►  février 2015 (3)
      • ►  janvier 2015 (1)
    • ►  2014 (8)
      • ►  décembre 2014 (1)
      • ►  novembre 2014 (1)
      • ►  octobre 2014 (1)
      • ►  août 2014 (2)
      • ►  juillet 2014 (2)
      • ►  janvier 2014 (1)
    • ►  2013 (53)
      • ►  décembre 2013 (2)
      • ►  novembre 2013 (1)
      • ►  octobre 2013 (3)
      • ►  septembre 2013 (2)
      • ►  août 2013 (5)
      • ►  juillet 2013 (3)
      • ►  juin 2013 (5)
      • ►  mai 2013 (3)
      • ►  avril 2013 (7)
      • ►  mars 2013 (7)
      • ►  février 2013 (11)
      • ►  janvier 2013 (4)
    • ►  2012 (105)
      • ►  décembre 2012 (8)
      • ►  novembre 2012 (5)
      • ►  octobre 2012 (4)
      • ►  septembre 2012 (1)
      • ►  août 2012 (8)
      • ►  juillet 2012 (7)
      • ►  juin 2012 (7)
      • ►  mai 2012 (10)
      • ►  avril 2012 (13)
      • ►  mars 2012 (15)
      • ►  février 2012 (15)
      • ►  janvier 2012 (12)
    • ►  2011 (146)
      • ►  décembre 2011 (14)
      • ►  novembre 2011 (11)
      • ►  octobre 2011 (12)
      • ►  septembre 2011 (13)
      • ►  août 2011 (15)
      • ►  juillet 2011 (17)
      • ►  juin 2011 (18)
      • ►  mai 2011 (15)
      • ►  avril 2011 (9)
      • ►  mars 2011 (7)
      • ►  février 2011 (3)
      • ►  janvier 2011 (12)
    • ▼  2010 (398)
      • ►  décembre 2010 (29)
      • ►  novembre 2010 (28)
      • ►  octobre 2010 (32)
      • ▼  septembre 2010 (34)
        • Goo.gl peut générer des codes QR
        • Nous sommes les débris de Dieu
        • Programmer en français ?
        • Profession : artiste Lego
        • La balise Meter en HTML 5
        • Citation no. 100 sur la langue
        • Top 4 des chansons pour envoyer promener quelqu'un
        • Pénurie de robots
        • Lieux de tournage de films et séries télé
        • Utiliser l'API de Bit.ly avec PHP
        • Suivre l'activité d'un serveur PostgreSQL
        • Impossible veut dire 25 heures
        • Première expérience en géocaching
        • Citation no. 99 sur les voitures
        • Attribut autofocus en HTML 5
        • Générer un PDF en PHP
        • Géolocalisation avec HTML 5
        • Une surprise se cache à l'intérieur !
        • Survol de l'audio en HTML 5
        • Attribut placeholder sur input HTML 5
        • Citation no. 98 sur le journal
        • Facture d'ordinateur acheté en 1996
        • Recette de Dr Pepper
        • Combien se vendait un PC en 1989 ?
        • Symphonie à 1 bit de Tristan Perich
        • Les Invincibles : les esprits parlent le latin
        • Allez-vous tirer l'ours ou pas ?
        • Énigme : obtenir la somme de 82
        • Attention à l'heure d'été en programmation
        • Citation no. 97 sur la prison
        • Totalement inutile
        • Nouveaux contrôles HTML 5
        • Hiérarchie dans une entreprise
        • Bière Melon Head de Picaroons
      • ►  août 2010 (22)
      • ►  juillet 2010 (35)
      • ►  juin 2010 (42)
      • ►  mai 2010 (36)
      • ►  avril 2010 (37)
      • ►  mars 2010 (34)
      • ►  février 2010 (32)
      • ►  janvier 2010 (37)
    • ►  2009 (430)
      • ►  décembre 2009 (32)
      • ►  novembre 2009 (34)
      • ►  octobre 2009 (33)
      • ►  septembre 2009 (37)
      • ►  août 2009 (37)
      • ►  juillet 2009 (39)
      • ►  juin 2009 (38)
      • ►  mai 2009 (37)
      • ►  avril 2009 (35)
      • ►  mars 2009 (37)
      • ►  février 2009 (32)
      • ►  janvier 2009 (39)
    • ►  2008 (84)
      • ►  décembre 2008 (34)
      • ►  novembre 2008 (39)
      • ►  octobre 2008 (11)

    Abonnés

Copyright © All Rights Reserved. Code 18 | Converted into Blogger Templates by Theme Craft