picture picture
décembre 20, 2019 PHP 0 Commentaire

[Tuto] Créer un PDF en PHP avec FPDF

Petit tutoriel FPDF pour la créer un fichier PDF en PHP avec données extraites d'une base des données, et incluant un tableau: cela suffit dans 95% des cas.

Créer un PDF dynamiquement avec PHP est un travail long, je dirais presque fastidieux…

La librairie gratuite FPDF simplifie sensiblement cette tâche, sans pour autant la rendre totalement intuitive. Concrètement, l’affichage des données s’apparente à un dessin créé avec les chaîne de caractères à afficher : tout doit être positionné à l’avance, il n’y aura dans la plupart des cas pas de retour à la ligne automatique (ni de redimensionnement selon la taille des écrans puisqu’il s’agit d’un format d’impression)

Voici un petit tutoriel FPDF de base, pour la créer un fichier PDF avec des données extraites d’une base des données et incluant un tableau : cela suffira à couvrir 95% des besoins…

Étape 1 : installer la librairie FPDF

Télécharger la librairie sur le site de FPDF > choisissez la version la plus récente au format ZIP.
Après extraction des fichiers, mettez les tous dans un dossier nommé fpdf par exemple, créé sur la racine de votre serveur (vous adapterez ce chemin pour la suite du tutoriel s’il est différent)

Étape 2 : connecter le fichier de création à la base des données

Créez un fichier nommé par exemple test.php (vous pourrez l’appeler dans un autre fichier si vous le souhaitez avec la fonction require_once())
Dans ce fichier, puisque nous partons du principe que les données sont extraites d’une base des données, vous allez commencer par vous connecter à la base, puis à la librairie FPDF elle-même.

Dans cet exemple, nous allons créer un PDF affichant le nombre de repas que chaque voyageur d’une agence de voyage aura pris par ville et par pays (c’est un voyage gastronomique ;) )

<?php
// Connexion à la BDD (à personnaliser)
$link = mysqli_connect('localhost','login','mot_de_passe','nom_base');
// Si base de données en UTF-8, il faudra utiliser la fonction utf8_decode() pour tous les champs de texte à afficher

// extraction des données à afficher dans le sous-titre (nom du voyageur et dates de son voyage)
$requete = "SELECT * FROM voyageur WHERE id_voyageur='1'";
$result = mysqli_query($link, $requete);
// tableau des résultats de la ligne > $data_voyageur['nom_champ']
$data_voyageur = mysqli_fetch_array($result);
mysqli_free_result($result);

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

Étape 3 : créer la classe FPDF, avec une en-tête et un pied de page

Dans cette classe, et pour cet exemple, on va définir une en-tête incluant un logo, un titre commun à toutes les pages, et un pied de page avec affichage d’un compteur de pages. Cette étape est facultatives si vous ne souhaitez ni en-tête ni pied de page. Toutes les valeurs de positionnement sont en mm (par défaut)
Les explications sont en commentaires : pour plus de détails voir les tutoriels du site FPDF ou le liste des fonctions

// Création de la class PDF
class PDF extends FPDF {
  // Header
  function Header() {
    // Logo : 8 >position à gauche du document (en mm), 2 >position en haut du document, 80 >largeur de l'image en mm). La hauteur est calculée automatiquement.
    $this->Image('logo_agence.png',8,2);
    // Saut de ligne 20 mm
    $this->Ln(20);

    // Titre gras (B) police Helbetica de 11
    $this->SetFont('Helvetica','B',11);
    // fond de couleur gris (valeurs en RGB)
    $this->setFillColor(230,230,230);
     // position du coin supérieur gauche par rapport à la marge gauche (mm)
    $this->SetX(70);
    // Texte : 60 >largeur ligne, 8 >hauteur ligne. Premier 0 >pas de bordure, 1 >retour à la ligneensuite, C >centrer texte, 1> couleur de fond ok  
    $this->Cell(60,8,'VOYAGE GASTRO',0,1,'C',1);
    // Saut de ligne 10 mm
    $this->Ln(10);    
  }
  // Footer
  function Footer() {
    // Positionnement à 1,5 cm du bas
    $this->SetY(-15);
    // Police Arial italique 8
    $this->SetFont('Helvetica','I',9);
    // Numéro de page, centré (C)
    $this->Cell(0,10,'Page '.$this->PageNo().'/{nb}',0,0,'C');
  }
}
									

Étape 4 : créer la première page avec les caractères par défaut

Il est possible de choisir si la page est au format portrait (P) ou paysage (L > Landscape), si les données sont affichées en mm ou en pixels, et le format d’impression final. On aurait pu par exemple demander une page A5 au format paysage et avec des calculs en points…

// On active la classe une fois pour toutes les pages suivantes
// Format portrait (>P) ou paysage (>L), en mm (ou en points > pts), A4 (ou A5, etc.)
$pdf = new PDF('P','mm','A4');

// Nouvelle page A4 (incluant ici logo, titre et pied de page)
$pdf->AddPage();
// Polices par défaut : Helvetica taille 9
$pdf->SetFont('Helvetica','',9);
// Couleur par défaut : noir
$pdf->SetTextColor(0);
// Compteur de pages {nb}
$pdf->AliasNbPages();
									

Étape 5 : afficher un sous-titre de page calé à gauche et encadré

Dans cet exemple, il y a 2 lignes de sous-titre : une avec la dates du voyage, l’autre, avec un nom-prénom du voyageur (précédemment extraits de la base à l’étape 1).
Chaque chaîne est insérée dans un cellule d’une seule ligne : Cell(). Par défaut cette cellule est positionnée à gauche :
– les 2 premiers chiffres correspondent à la largeur et la hauteur de la cellule (ne pas oublier qu’une page A4 fait 210 mm de large, moins les marges : testez !)
– ensuite vient le texte à afficher décodée en UTF8 (cette étape dépend de l’encodage de votre base des données et de celui de la page)
– ensuite la présence (1) ou non (0) d’une bordure autour de la cellule. On peut remplacer le « 1 » par les positions de la bordure éventuelle (L>gauche, T>haut, R>droite, B>bas) : par ex. « LR » pour un encadrement sur les bords droite et gauche. L’ordre de déclaration est indifférent.
– ensuite le positionnement de la cellule suivante (valeur facultative : mettez 1 pour positionner le curseur au début de la ligne suivante.
– ensuite l’alignement du texte (L>à gauche, C>centré, R>à droite)
– ensuite le remplissage (1) ou non (0) de la cellule par une couleur de fond (ou rien, s’il n’y a pas de background déclaré précédemment)
Quand une valeur est omise ou égale à zéro, elle prend la valeur par défaut (texte à gauche sur fond transparent et sans retour chariot ensuite)


Vous pouvez aussi utiliser la fonction Text() : personnellement je l’utilise peu mais elle est équivalente.

// Sous-titre calées à gauche, texte gras (Bold), police de caractère 11
$pdf->SetFont('Helvetica','B',11);
// couleur de fond de la cellule : gris clair
$pdf->setFillColor(230,230,230);
// Cellule avec les données du sous-titre sur 2 lignes, pas de bordure mais couleur de fond grise
$pdf->Cell(75,6,'DU '.$data_voyageur['date_deb'].' AU '.$data_voyageur['date_fin'],0,1,'L',1);    
$pdf->Cell(75,6,strtoupper(utf8_decode($data_voyageur['prenom'].' '.$data_voyageur['nom'])),0,1,'L',1);        
$pdf->Ln(10); // saut de ligne 10mm
									

Étape 6 : créer la fonction d’affichage de l’en-tête d’un tableau

Un petit peu plus de calculs de positions : c’est juste du dessin, avec des abscisses (X) et des ordonnées (Y) !
$pdf->SetX(xx) déclare que le coin supérieur gauche du tableau va être à xx mm de la marge de la page (abscisse).
On positionne donc les cellules d’en-tête les unes à côté des autres, en calculant chaque fois la nouvelle position xx de son coin supérieur gauche (on additionne aux largeurs des cellules précédentes). Chaque cellule peut avoir une largeur différente de ses voisines, déclarée dans la fonction Cell() comme vu précédemment.

// Fonction en-tête des tableaux en 3 colonnes de largeurs variables
function entete_table($position_entete) {
  global $pdf;
  $pdf->SetDrawColor(183); // Couleur du fond RVB
  $pdf->SetFillColor(221); // Couleur des filets RVB
  $pdf->SetTextColor(0); // Couleur du texte noir
  $pdf->SetY($position_entete);
  // position de colonne 1 (10mm à gauche)  
  $pdf->SetX(10);
  $pdf->Cell(60,8,'Ville',1,0,'C',1);  // 60 >largeur colonne, 8 >hauteur colonne
  // position de la colonne 2 (70 = 10+60)
  $pdf->SetX(70); 
  $pdf->Cell(60,8,'Pays',1,0,'C',1);
  // position de la colonne 3 (130 = 70+60)
  $pdf->SetX(130); 
  $pdf->Cell(30,8,'Repas',1,0,'C',1);

  $pdf->Ln(); // Retour à la ligne
}
// AFFICHAGE EN-TÊTE DU TABLEAU
// Position ordonnée de l'entête en valeur absolue par rapport au sommet de la page (70 mm)
$position_entete = 70;
// police des caractères
$pdf->SetFont('Helvetica','',9);
$pdf->SetTextColor(0);
// on affiche les en-têtes du tableau
entete_table($position_entete);
									

Étape 7 : remplir dynamiquement les lignes du tableau

Il s’agit d’une simple extraction en boucle d’une base MySQL. Les valeurs extraites s’affichent dans des cellules avec la fonction MultiCell() qui supportent les retour à la ligne automatique, puisque par défaut on ignore la longueur des chaînes variables extraites.
Cette fonction a à peu près le même fonctionnement que la fonction Cell() :
largeur > hauteur > texte > bordure > alignement > remplissage.
La seule nouveauté est l’apparition d’une fonction SetY() qui permet de positionner le coin supérieur gauche de chaque ligne de cellule, non seulement par rapport à la marge de gauche (SetX : abscisse), mais également par rapport à la marge du haut de page (SetY : ordonnée).

$position_detail = 78; // Position ordonnée = $position_entete+hauteur de la cellule d'en-tête (60+8)
$requete2 = "SELECT * FROM gastro WHERE id_voyageur='1'";
$result2 = mysqli_query($link, $requete2);
while ($data_visit = mysqli_fetch_array($result2)) {
  // position abcisse de la colonne 1 (10mm du bord)
  $pdf->SetY($position_detail);
  $pdf->SetX(10);
  $pdf->MultiCell(60,8,utf8_decode($data_visit['ville']),1,'C');
    // position abcisse de la colonne 2 (70 = 10 + 60)  
  $pdf->SetY($position_detail);
  $pdf->SetX(70); 
  $pdf->MultiCell(60,8,utf8_decode($data_visit['pays']),1,'C');
  // position abcisse de la colonne 3 (130 = 70+ 60)
  $pdf->SetY($position_detail);
  $pdf->SetX(130); 
  $pdf->MultiCell(30,8,$data_visit['nb_repas'],1,'C');

  // on incrémente la position ordonnée de la ligne suivante (+8mm = hauteur des cellules)  
  $position_detail += 8; 
}
mysqli_free_result($result2);
									

Étape 8 : créer une nouvelle page

Aucune déclaration n’est nécessaire pour terminer une page. Le footer s’insère automatiquement en bas de page s’il a été déclaré.
Mais ATTENTION ! C’est à vous de calculer le bon nombre de lignes pour que le flux d’extraction ne dépassent pas la hauteur de la page !

S’il est nécessaire de créer une nouvelle page, c’est très simple : il vous suffira d’ajouter ensuite dans le code une fonction AddPage() :
elle a pour effet d’insérer une nouvelle en-tête, un nouveau footer (avec un compteur de page incrémenté si vous en avez inséré un), et de positionner la curseur en haut à droite de la nouvelle page. Vous pouvez si vous le souhaitez modifier les caractéristiques des polices de caractères de cette page, sinon ce sont les valeurs de l’en-tête qui prévalent.

// Nouvelle page PDF
$pdf->AddPage();
// Polices par défaut : Helvetica taille 9
$pdf->SetFont('Helvetica','',11);
// Couleur par défaut : noir
$pdf->SetTextColor(0);
// Compteur de pages {nb}
$pdf->AliasNbPages();
$pdf->Cell(500,20,utf8_decode('Plus rien à vous dire ;-)'));
									

Étape 9 : exporter le PDF

2 solutions :
1. Soit vous voulez afficher/exporter le PDF (utile en phase de création et de test). En ce cas vous utilisez la fonction output() avec :
– le premier argument qui donne le nom du fichier PDF,
– le second argument qui donne l’ordre d’afficher sur le navigateur internet (I >Inline), ou de forcer le téléchargement du fichier (D > Download)

 // affichage à l'écran...
$pdf->Output('test.pdf','I');
									

2. Soit vous souhaitez stocker ce fichier PDF sur votre serveur (pour l’envoyer dans un second temps par e-mail en pièce jointe, par exemple)
En ce cas vous utiliserez également la fonction output(), mais avec :
– comme premier argument F (> File),
– et comme second argument le chemin de destination du fichier (plus besoin de préciser le nom du fichier, puisqu’il apparait sur cette chaîne) :

 // ...ou export sur le serveur dans un dossier "fic"
$pdf->Output('F', '../fic/test.pdf');
?>
									

Afficher le résultat

Cliquez ici pour afficher le PDF à l’écran

Télécharger les fichiers de ce tutoriel

Cliquez ici pour télécharger tous les fichiers de ce tutoriel

Et les images ?

Parce qu’une bonne image, justement, vaut mieux qu’un long discours !

source : https://www.plus2net.com/

That’s all folk ! Bon courage :)

No Responses to “[Tuto] Créer un PDF en PHP avec FPDF”

Commentaire

Name

Mail (ne sera pas publié)

Website

Laisser ces deux champs tels quels :
:D :-) :( :o 8O :? 8) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: