Tutoriel : créer un fichier PDF avec FPDF

Tutoriel : créer un fichier PDF avec FPDF

Encore un billet en rapport avec un tutoriel. Mais cette fois-ci, c'est un brin plus compliqué à mettre en place. Sans vous livrer tous mes secrets de fabrication, je vais vous livrer quelques bases pour construire un fichier PDF à partir d'une base de données.

Utilisation de la librairie FPDF

Pour ce tutoriel, nous allons avoir besoin de la librairie FPDF. Grâce aux fonctions de base, nous allons pouvoir construire de nombreux types de documents. Pour ce tutoriel, je vais vous proposer un mélange d'informations afin d'utiliser au maximum les possibilités de FPDF. Uploadez la librairie FPDF sur votre serveur.

C'est parti ! Nous devons créer un fichier nommé pdf.php par exemple que l'on commence à remplir comme suit :

<?php
// Connexion à la BDD
$bddname = 'nom_de_la_base';
$hostname = 'localhost';
$username = 'utilisateur';
$password = 'mot_de_passe';
$db = mysqli_connect ($hostname, $username, $password, $bddname);

// Appel de la librairie FPDF
require("fpdf/fpdf.php");

A partir de là, nous pouvons commencer à afficher des données. Pour info, si votre base de données est en UTF-8, vous devrez utiliser la fonction utf8_decode pour tous les champs contenant du texte. Rien de bien sorcier, mais il faut y penser pour éviter les caractères exotiques.

Commençons par afficher un logo en header et les coordonnées en footer. Tout le code qui suit sera à ajouter au précédent. Ça m'évitera d'avoir des lignes de code trop longues. :)

// Création de la class PDF
class PDF extends FPDF {
    // Header
    function Header() {
        // Logo
        $this->Image('images/logo-infiniblog.jpg',8,2,80);
        // Saut de ligne
        $this->Ln(20);
    }
    // Footer
    function Footer() {
        // Positionnement à 1,5 cm du bas
        $this->SetY(-15);
        // Adresse
        $this->Cell(196,5,'Mes coordonnées - Mon téléphone',0,0,'C');
    }
}

Je vous ai perdu ? Ne partez pas, je vous explique. Pour le header, je souhaite afficher un logo. J'appelle donc mon image en indiquant le chemin. Le chiffre 8 correspond à la position à gauche du document, le 2 à la position en haut du document et le 80 à la largeur de l'image. La hauteur est calculée automatiquement.

Pour le footer, j'utilise la fonction Cell pour créer une ligne. Le chiffre 196 correspond à la largeur de la ligne et le chiffre 5 à la hauteur. Ensuite j'écris mon texte (ne pas oublier d'échapper les apostrophes). Le premier 0 indique que je ne souhaite pas de bordure, le second qu'il ne doit pas y avoir de retour à la ligne et le C indique que je souhaite centrer mon texte.

Avant d'afficher le PDF, il faut activer la classe et définir quelques paramètres tels que le format du PDF (portrait, en mm et A4) la police et sa taille, ainsi que la couleur du texte par défaut. La fonction AddPage créée le document et permet d'afficher notamment le logo et les coordonnées en pied de page.

// Activation de la classe
$pdf = new PDF('P','mm','A4');
$pdf->AddPage();
$pdf->SetFont('Helvetica','',11);
$pdf->SetTextColor(0);

Voilà concrètement ce que donne l'affichage des ces informations : voir le PDF.

Construire le document depuis la base de données

Nous partons du principe que nous possédons une base de données avec plusieurs tables. Pour l'exemple, je dispose de données clients et de données commandes.

Commençons par afficher deux blocs d'informations. Celui de la commande et les coordonnées du client.

$req = "SELECT id, id_client, date_com, reglement FROM table_commandes WHERE id=".$_GET['id'];
$rep = mysqli_query($db, $req);
$row = mysqli_fetch_array($rep);

// Infos de la commande calées à gauche
$pdf->Text(8,38,'N° de facture : '.$row['id']);
$pdf->Text(8,43,'Date : '.$row['date_com']);
$pdf->Text(8,48,'Mode de règlement : '.$row['reglement']);

Pour la fonction Text, les deux chiffres correspondent à la position gauche puis la position haut pour le placement des informations. Donc on cale ces infos à 8mm de la gauche et 43mm du haut du PDF pour la première ligne. On ajoute 5mm par ligne pour caler les infos les unes en dessous des autres.

$req1 = "SELECT nom, prenom, adresse, code_postal, ville FROM table_clients WHERE id=".$row['id_client'];
$rep1 = mysqli_query($db, $req1);
$row1 = mysqli_fetch_array($rep1);

// Infos du client calées à droite
$pdf->Text(120,38,utf8_decode($row1['prenom']).' '.utf8_decode($row1['nom']));
$pdf->Text(120,43,utf8_decode($row1['adresse']));
$pdf->Text(120,48,$row1['code_postal'].' '.utf8_decode($row1['ville']));

Pour afficher le bloc adresse à droite, j'ai remplacé le premier chiffre 8 par 120. A vous de peaufiner le calage selon vos besoins. Voyons ce que donne le PDF avec ces informations supplémentaires : voir le PDF.

Construction d'un tableau

La ça va nettement se compliquer puisque l'on va construire un tableau pour afficher les lignes de la commande avec un entête doté d'une couleur en background. Qui dit tableau, dit multi-colonnes et filets pour délimiter l'ensemble. Vous pouvez au choix prendre un Doliprane ou vous faire un café. ;)

On commence par créer l'entête du tableau avec quelques paramètres et une fonction dédiée selon le code suit :

// Position de l'entête à 10mm des infos (48 + 10)
$position_entete = 58;

function entete_table($position_entete){
    global $pdf;
    $pdf->SetDrawColor(183); // Couleur du fond
    $pdf->SetFillColor(221); // Couleur des filets
    $pdf->SetTextColor(0); // Couleur du texte
    $pdf->SetY($position_entete);
    $pdf->SetX(8);
    $pdf->Cell(158,8,'Désignation',1,0,'L',1);
    $pdf->SetX(166); // 8 + 96
    $pdf->Cell(10,8,'Qté',1,0,'C',1);
    $pdf->SetX(176); // 104 + 10
    $pdf->Cell(24,8,'Net HT',1,0,'C',1);
    $pdf->Ln(); // Retour à la ligne
}
entete_table($position_entete);

Le premier $pdf->SetX(8) est la position de la première colonne, soit 8mm de la gauche. La valeur 158 correspond à la largeur de la colonne, le 8 à la hauteur. Ensuite le libellé de la colonne, le 1 pour indiquer que l'on souhaite un filet de 1mm, le 0 pour le saut de ligne, le C pour centrer le texte et le 1 pour afficher la couleur de fond.

Vous suivez toujours ? Donc si c'est OK, nous allons afficher les détails de la commande. Pour ce faire, nous allons utiliser la fonction MultiCell, pour créer plusieurs lignes comme son nom l'indique. ;)

// Liste des détails
$position_detail = 66; // Position à 8mm de l'entête

$req2 = "SELECT libelle, qte, prix_ht FROM table_details WHERE id_commande=1";
$rep2 = mysqli_query($db, $req2);
while ($row2 = mysqli_fetch_array($rep2)) {
    $pdf->SetY($position_detail);
    $pdf->SetX(8);
    $pdf->MultiCell(158,8,utf8_decode($row2['libelle']),1,'L');
    $pdf->SetY($position_detail);
    $pdf->SetX(166);
    $pdf->MultiCell(10,8,$row2['qte'],1,'C');
    $pdf->SetY($position_detail);
    $pdf->SetX(176);
    $pdf->MultiCell(24,8,$row2['prix_ht'],1,'R');
    $position_detail += 8;
}

Comme vous le voyez, on appelle les détails de la commande en utilisant while. Comme cela, le script remontera toutes les lignes en rapport avec notre commande. Pour les chiffres, nous avons indiqué les mêmes que l'entête afin de caler les détails sur l'entête. Le 1 et le C, L ou R (centre, left ou right) correspondent à l'affichage du filet et à la position de l'info dans la colonne.

La petite nuance concerne la dernière ligne. Puisque nous sommes dans un while, il faut préciser que chaque nouvelle ligne est positionnée à 8mm en dessous de la précédente.

Il faut penser à donner un nom à votre document PDF lorsque vous souhaitez le télécharger et fermer le document pdf.php :

// Nom du fichier
$nom = 'Facture-'.$row['id'].'.pdf';

// Création du PDF
$pdf->Output($nom,'I');?>

Nous obtenons un superbe tableau en seulement quelques lignes de code : voir le PDF.

Voilà c'est fini

Ce tutoriel est à présent terminé. Je vous laisse réfléchir pour afficher d'autres informations comme le total de la facture, une ligne avec un RIB par exemple en cas de paiement par virement ou encore les informations obligatoires à faire apparaître sur une facture (taux de pénalité, indemnité forfaitaire, etc.). Il est tout à fait possible de créer des documents très intéressantes dès que l'on fait travailler ses neurones.

Modèle de document PDF

Une fois que vous maîtriserez ce code, il suffit de 15/20 minutes maxi pour monter le PDF d'une facture. Par contre, pour d'autres documents, faites couler une cafetière, préparez un paquet de gâteaux et armez vous de patience.

Pour la petite info, il m'est arrivé de bosser 5/6 jours sur un même document. Notamment lorsque vous avez une trame en background et qu'il faut placer des données dans des cases comme le code postal par exemple. Il faut décomposer la donnée pour placer chaque chiffre dans les 5 cases prévues à cet effet. Je ne vous dis pas la prise de tête parfois. :)

Catégorie Tutoriels - Écrit par le 02/12/2014 - Article lu 9 644 fois - 5 commentaires

5 réflexions sur ce billet

Écrit par Adrien
Le 10/12/2014 à 02h39

Sinon il existe des librairies HTML to PDF (html2pdf, dompdf). Tellement plus pratique.

Écrit par unequicheeninfo
Le 23/04/2015 à 03h19

Merci beaucoup :D

Écrit par boris yao
Le 02/09/2015 à 18h49

Merci beaucoup ! Votre tutoriel ma vraiment sauvé. Dieu vous bénisse.

Écrit par Duduche75
Le 06/12/2015 à 23h10

Vraiment un grand merci pour la clarté de ces explications. Bravo.

Écrit par Dudu75
Le 01/02/2016 à 00h36

Merci.
Petite question : comment imprimer la bonne hauteur du tableau par rapport au besoin de lignes de la facture ?

Les commentaires de ce billet sont fermés

Haut de page