Choisir la bonne librairie PDF en PHP

Générez des fichiers PDF via PHPIl y a un certain nombre de librairies PDF qui peuvent vous aider à générer des fichiers PDF via PHP : FPDF, TCPDF, DOMPDF, CEZPDF…

J’ai longtemps travaillé avec FPDF qui est une classe très légère (le fichier fpdf.php pèse 49ko), facile à implémenter mais avec des fonctions un peu basiques.

TCPDF m’a tout d’abord conquis parce qu’elle permet d’envoyer de l’HTML (tableaux, css,…) à la classe. Ceci est une grande avancée puisqu’il n’est plus nécessaire de définir les abscisses et ordonnées de toutes les informations à faire apparaître sur le PDF. Le tableau HTML est affiché comme dans une page Web. Elle offre aussi des outils de transformation qui permettent par exemple d’afficher du texte à 90 degrés, par exemple. Mais la classe TCPDF est beaucoup trop lourde : 963 ko. J’utilise des scripts AJAX pour générer une grande quantité de fichiers PDF et ces scripts doivent charger la classe de 1Mo à chaque AJAX call, ce qui rend le temps de génération des fichiers PDF extrêmement long. J’ai bien essayé d’alléger la classe et enlevant tous les commentaires mais il restait quand même un fichier de 500Ko à charger.

J’ai donc décidé de revenir à FPDF et ai trouvé une classe qui étend la classe FPDF pour autoriser la rotation de texte sur le fichier PDF.

Ce tuto décrira l’implémentation de la classe FPDF (et ses classes de rotation) dans le framework PHP Codeigniter 2.0.3.

Tout d’abord, téléchargez la classe FPDF. Vous la trouverez sur la page de téléchargement de http://www.fpdf.org. Avec la classe PHP fpdf.php, vous trouverez des tutoriels et des docs dans le fichier téléchargé.

Copiez simplement le fichier fpdf.php dans /Codeigniter_2.0.3/application/libraries/ et copiez le répertoire font/ dans /Codeigniter_2.0.3/application/third_party/fpdf/

Allez ensuite sur http://www.fpdf.org/fr/script/script2.php où vous trouverez 2 classes à copier dans le même répertoire libraries/ :

  • la classe FPDF_Rotate, une extension de la classe FPDF
  • la classe PDF, une extension de la classe FDPF_Rotate

En créant ces 2 classes dans Codeigniter, suivez bien les conseils de CI concernant la création de libraries. Au besoin, vous trouverez les fichiers attachés en bas de ce tutoriel.

Vous définirez ensuite le chemin vers le répertoire font de FPDF dans /Codeigniter_2.0.3/application/config/config.php :

//FPDF FONT DIRECTORY
$config['fonts_path'] = APPPATH.'third_party/fpdf/fonts/';

Enfin, dans votre controller, appelez simplement la librairie et définissez les items nécessaires :
define('FPDF_FONTPATH',$this->config->item('fonts_path'));
$this->load->library(array('fpdf','fpdf_rotate','pdf'));
$this->pdf->Open();
$this->pdf->SetFont('Arial', '', 12);
$this->pdf->SetDrawColor(0);
$this->pdf->RotatedText(10,40,'Hello World!',90);
$this->pdf->MultiCell(100,5,"Test\nSecond line");
$this->pdf->Output('./pdfs/test.pdf', 'F');

Vous pouvez télécharger les fichiers nécessaires : fichiers de la classe pdf

Webliography :

FPDF Class

TCPDF

DOMPDF

Choosing the right PDF library in PHP

Generate pdf files with PHPThere are a number of PDF libraries that can help you dynamically generate .PDF files through PHP : FPDF, TCPDF, DOMPDF, CEZPDF…

I’ve long worked with FPDF which is very light (with a core file of 49ko), easy to implement but the functions provided are limited.

TCPDF first astonished me since it is able to display pure HTML in a pdf file (tables, css,… support). It also provides transformation functions that allow you to display text vertically on a .pdf file, for example. But the TCPDF core file is much too heavy : 963 ko. I run AJAX scripts that load that library at each AJAX call, which makes the time waiting for the .pdf files to be ready much too long. So, I’ve tried to make that class lighter and got rid of all comments it contained. But I still had more than 500ko of file.

I then decided to go back to FPDF and found an extension class that allows FPDF to rotate text on a page.

This tutorial is devoted to implementing FPDF (and rotation class) in PHP framework Codeigniter 2.0.3.

First download the FPDF class. You’ll find it in the download page of http://www.fpdf.org. Along with the fpdf.php class, you’ll find tutorials and docs in the downloaded file

Simply copy the file fpdf.php to /Codeigniter_2.0.3/application/libraries/ and copy the font/ directory to /Codeigniter_2.0.3/application/third_party/fpdf/

Then go to http://www.fpdf.org/fr/script/script2.php where you’ll find two classes you’ll copy in the same libraries directory:

  • The FPDF_Rotate class as an extension of the FPDF class
  • The PDF class as an extension of the FDPF_Rotate class

Be careful when creating those two libraries in Codeigniter to follow Codeigniter’s tips on creating libraries. You’ll find the files attached to the bottom of this tutorial.

You’ll also have to define the path to the FPDF font directory in /Codeigniter_2.0.3/application/config/config.php :

//FPDF FONT DIRECTORY
$config['fonts_path'] = APPPATH.'third_party/fpdf/fonts/';

Then, in your controller, simply call the library and set the necessary items :
define('FPDF_FONTPATH',$this->config->item('fonts_path'));
$this->load->library(array('fpdf','fpdf_rotate','pdf'));
$this->pdf->Open();
$this->pdf->SetFont('Arial', '', 12);
$this->pdf->SetDrawColor(0);
$this->pdf->RotatedText(10,40,'Hello World!',90);
$this->pdf->MultiCell(100,5,"Test\nSecond line");
$this->pdf->Output('./pdfs/test.pdf', 'F');

You can download the necessary files : fpdf class files

Webliography :

FPDF Class

TCPDF

DOMPDF

Polymorphisme et PHP5

Le polymorphisme est un concept majeur de la Programmation Orientée Objet (POO). Des langages mûrs tels que C++ ou JAVA intègrent ce concept de manière native. PHP5 permet également d’intégrer le polymorphisme dans le développement PHP.

Qu’est-ce que le polymorphisme?

Son principe réside dans son nom : [poly-] signifie beaucoup et [-morphisme] signifie formes, états. Ainsi, intégrer le polymorphisme dans la programmation permet au développeur d’initialiser un seul objet qui se comportera différemment selon son type. Pratiquement parlant, le développeur écrit une classe de base qui définit les attributs de l’objet et autant de sous-classes que de comportements différents de l’objet seront nécessaires.

Voici un exemple simple de design polymorphique dans le cadre d’un objet véhicule. La classe véhicule a pour attributs des informations qui valent pour tout type de véhicule : marque, date d’achat, prix d’achat :

Class Vehicule {

 

protected $marque;
protected $date_achat;
protected $prix_achat;
public function __construct($marque,$date_achat,$prix_achat) {
$this->marque = $marque;
$this->date_achat = $date_achat;
$this->prix_achat = $prix_achat;
}

}

On peut ensuite créer la classe avion et la classe voiture héritant de la classe véhicule :

Class Voiture Extends Vehicule {

private $cylindree;
private $km;
public function __construct($array) {
parent::__construct($array["marque"],$array["date_achat"],$array["prix_achat"]);
$this->cylindree = $array["cylindree"];
$this->km = $array["km"];
}
}

Class Avion Extends Vehicule {

private $type;
private $heures_vol;
public function __construct($array) {
parent::__construct($array["marque"],$array["date_achat"],$array["prix_achat"]);
$this->type = $array["type"];
$this->heures_vol = $array["heures_vol"];
}

}

Structurer vos classes de cette manière permet de rendre votre programmation orientée objet plus abstraite, et donc plus flexible. Changer un type d’objet particulier après production sera plus aisé et plus stable.

Objets sans design polymorphique

Créer une classe de génération de champs de formulaire sans polymorphisme :

<?php
class Form {
public function genInput($type,$name,$value) {
SWITCH($type) {
Case »text »:
print « <input type=\ »text\ » name=\ »".$name. »\ » value=\ »".$value. »\ » />\r\n »;
break;
Case »textarea »:
print « <textarea name=\ »".$name. »\ »> ».$value. »</textarea>\r\n »;
break;
}
}
}
$form = new Form(); //initialisation de l’objet formulaire
$form->genInput(« text », »field1″, »Lorem ipsum… »); //affiche <input type= »text » name= »field1″ value= »Lorem ipsum… » />
$form->genInput(« textarea », »field2″, »Lorem ipsum… »); //affiche <textarea name= »field2″>Lorem ipsum…</textarea>
?>

Objets avec design polymorphique

Pour qu’un objet puisse revêtir plusieurs formes, qu’il s’agisse d’un champ texte ou d’un champ textarea, nous devons rendre notre classe plus abstraite.
Nous allons donc créer une interface, une classe abstraite et quelques sous-classes (selon le type de champ).
L’interface définira les fonctions que l’objet appellera sans définir ce que ces fonctions feront. L’interface ne définira aucune des fonctionnalités de ces méthodes, elle se contente de les nommer. Chaque sous-classe devra comporter la définition de la méthode genInput().

//INTERFACE
interface Form {

public function genInput();

}

Une classe abstraite est une classe qui nous n’implémentons que partiellement. Elle contient les méthodes (fonctions) abstraites qui offrent des fonctionnalités communes. Le reste des autres fonctioannlités sera défini dans les sous-classes.
//ABSTRACT CLASS
abstract class Input {
protected $name;
protected $value;
public function __construct($name,$value) {
$this->name = $name;
$this->value = $value;
}
}
Puis les classes dérivées appelleront la méthode définie dans la classe abstraite (parent::__construct()) et la méthode nommée dans l’interface (genInput()) :
//TEXT & PASSWORD & HIDDEN INPUT
class Text extends Input implements Form {
private $type;
private $size;
public function __construct($array) {
parent::__construct($array["name"],$array["value"]);
$this->type = $array["type"];
$this->size = $array["size"];
}
public function genInput() {
return « <input type=\ »".$this->type. »\ » name=\ »".$this->name. »\ » value=\ »".$this->value. »\ » size=\ »".$this->size. »\ » />\r\n »;
}
}
//TEXTAREA INPUT
class Textarea extends Input implements Form {
private $cols;
private $rows;
public function __construct($array) {
parent::__construct($array["name"],$array["value"]);
$this->cols = $array["cols"];
$this->rows = $array["rows"];
}
public function genInput() {
return « <textarea name=\ »".$this->name. »\ » cols=\ »".$this->cols. »\ » rows=\ »".$this->rows. »\ »> ».$this->value. »</textarea>\r\n »;
}
}
Voici comment créer un champ texte :
$object = new Text(array(« type »=> »text », »name »=> »form_id », »value »=>$item, »size »=>20));
$hidden = $object->genInput();
Générer un champ textarea ressemble à ceci :
$object = new Textarea(array(« name »=> »form_txta », »value »=>$item , »cols »=>20 , »rows »=>5));
$textarea = $object->genInput();
Webliography :

Abstract classes and interfaces
Devshed polymorphism in PHP5 article
PHP5 Tutorial : Abstract classes and Interfaces
PHP5 OOP abstract classes & interfaces