Architecture Dolibarr : PDF en 30 jours

Comment structurer le développement, la mise en production et la génération de PDF avec Dolibarr en un mois ?


1️⃣ Introduction générale

Dolibarr est un ERP/CRM open‑source entièrement écrit en PHP, conçu pour être simple à installer, à personnaliser et à étendre.
Sa force réside dans une architecture modulaire qui sépare :

Niveau Description
Core Le noyau (fichiers core + core/modules) qui assure la logique métier, la gestion des modèles de données (PDO) et le système d’autorisations.
Modules Applications dédiées (ex : facturation, stocks, feuilles de temps) implémentées comme des plugins. Chaque module possède son own dossier (htdocs/modules/<module>), ses tables, ses hooks et ses points d’entrée (admin, crontab, etc.).
Themes & Templates Le rendu HTML est géré par le template engine intégré (<<<smarty‑based) ou par les skin modernes (htmltemplate).
Plugins Extensions tierces (ex : PDF Generator, QR Code, API, etc.) distribuées sous la forme d’un zip contenant manifest.xml, install.php, remove.php et le code PHP/HTML.

Cette structure permet de traduire rapidement un besoin métier (comme la génération de PDF) en un module ou un plugin dédié, tout en conservant la compatibilité avec les futures mises à jour du core.


2️⃣ Plan de projet « PDF en 30 jours »

Semaine Objectifs clés Livrables
S1 (Jour 1‑7) Analyse fonctionnelle, mise en place de l’environnement, création du repo Git. Diagramme de flux fonctionnel, README, Dockerfile.
S2 (Jour 8‑14) Installation de Dolibarr, développement du module “PDF Generator”. Docker‑compose fonctionnel, module “pdfgen” installé.
S3 (Jour 15‑21) Implémentation des points d’entrée (menu, bouton generate), intégration de la lib PDF (FPDF / TCPDF). Page « Generate PDF » fonctionnelle, tests unitaires.
S4 (Jour 22‑30) Optimisation, documentation, tests d’intégration, mise en production. Rapport de bugs, guide d’utilisation, packaging du module.

Note : chaque jour de travail est estimé à ~6 h (développement + revue). Le planning ci‑dessus est volontairement conservateur afin de laisser du temps aux imprévus.


3️⃣ Mise en place de l’environnement (Jour 1‑3)

  1. Prérequis

    • PHP ≥ 8.2 avec extensions pdo_mysql, mbstring, gd, zip.
    • Composer 2 (pour gérer les dépendances tierces).
    • Docker + Docker‑Compose (ou serveur LAMP traditionnel).

  2. Structure du repo « `bash
    ├─ .docker/
    │ └─ Dockerfile
    ├─ .compose/
    │ └─ docker-compose.yml
    ├─ src/ # Racine Dolibarr
    │ └─ htdocs/
    │ └─ dolibarr/
    │ ├─ core/
    │ └─ modules/
    └─ pdfgen/ # Module personnalisé
    ├─ manifest.xml
    ├─ install.php
    ├─ remove.php
    └─ class/
    └─ PdfGenerator.php
    └─ README.md

  3. Docker‑Compose (exemple minimal)

    version: "3.8"
    services:
    php:
    build: .docker
    volumes:
    - ./src:/var/www/html
    ports:
    - "8080:80"
    environment:
    - APACHE_DOCUMENT_ROOT=/var/www/html/public
    depends_on:
    - db db:
    image: mysql:8.0
    environment:
    MYSQL_ROOT_PASSWORD: secret
    MYSQL_DATABASE: dolibarr
    MYSQL_USER: dolibarr
    MYSQL_PASSWORD: secret
    volumes:
    - db_data:/var/lib/mysql
    volumes:
    db_data:

  4. Déploiement
    « `bash cd .compose
    docker compose up -d –build


    Accéder à `http://localhost:8080` → installer Dolibarr via l’URL d’installation (étape standard d’initialisation).


4️⃣ Création du module “PDF Generator”

4.1 Manifest & points d’entrée

pdfgen/manifest.xml (extrait)

<?xml version="1.0" encoding="UTF-8"?>
<manifest version="1.0">
<name>PDF Generator</name>
<version>1.0.0</version>
<author>Team PDF</author>
<description>Génération de PDF à la volée avec FPDF.</description>
<files>
<file method="install">class/PdfGenerator.php</file>
<file method="install">manifest.xml</file>
</files>
<hooks>
<hook type="combobox" target="leftmenu" name="PDF Generator" url="index.php?controller=pdfgen" />
</hooks>
</manifest>

  • Hook : ajoute le lien « PDF Generator » dans le menu de gauche.
  • Method install : copie le fichier dans le répertoire du module et enregistre les paramètres de configuration.

4.2 Classe principale pdfgen/class/PdfGenerator.php

<?php
namespace Dolibarr\Pdfgen;
use Dolibarr\Core\HookAPI;
use Dolibarr\Core\HTML;
use Dolibarr\Main\DolApplicationFramework as DolibarrApp;
class PdfGenerator
{
protected $fpdf;
protected $moduleDir;
public function __construct()
{
// Chemins spécifiques au module $this->moduleDir = dirname(__DIR__) . DIRECTORY_SEPARATOR;
// Instanciation de FPDF (ou TCPDF) en mode « stand‑alone »
$this->fpdf = new \FPDF('P','mm','A4');
}
/**
* Génère le PDF à partir d’un template HTML fourni.
*
* @param array $data Tableau des variables à injecter
* @param string $tpl_path Chemin du fichier HTML template
* @return string Le chemin du PDF généré (ou un flux)
*/
public function generate(string $data, string $tpl_path): string
{
// 1️⃣ Récupère le contenu du template
$html = file_get_contents($tpl_path);
// 2️⃣ Injection des variables
foreach ($data as $k=>$v) {
$html = str_replace('{{'.$k.'}}', htmlspecialchars($v), $html);
}
// 3️⃣ Convertit HTML → PDF avec bipass de la librairie FPDF
// Utilisation d’un moteur HTML‑to‑PDF léger (dompdf ou wkhtmltopdf)
// Ici, on se repose sur dompdf (via Composer)
require_once $this->moduleDir . 'vendor/autoload.php';
$dompdf = new \Dompdf\Dompdf();
$dompdf->loadHtml($html);
$dompdf->render();
// 4️⃣ Export du PDF dans un fichier temporaire
$pdf_path = $this->moduleDir . 'tmp/generated_' . uniqid() . '.pdf';
$dompdf->stream($pdf_path, ['Attachment'=>0]); // 0 = ne propose pas le téléchargement
return $pdf_path;
}
}

Astuce : Vous pouvez remplacer la dépendance dompdf par TCPDF (plus autonome) si vous ne voulez pas installer de nouvelles extensions système.

4.3 Installation du module

pdfgen/install.php

<?php
if (!defined('DOL_ROOT')) define('DOL_ROOT', realpath(dirname(__FILE__)..'/../../..'));
require_once Dolibarr::coreLoad('core/modules/DolModule.php');
class PdfGenerator extends DolModule
{
public function __construct()
{
$this->name = 'pdfgen';
$this->modulename = 'pdfgen';
$this->module_path = 'pdfgen';
$this->dir_main = 'modules';
parent::__construct();
// Création du répertoire temporaire (si besoin)
$tmp = $this->dir_module . 'tmp';
if (!is_dir($tmp)) mkdir($tmp, 0775, true);
}
public function install()
{
// Pas de tables à créer, seulement le module…
return parent::install();
}
public function uninstall()
{
// Supprimer le répertoire tmp…
$tmp = $this->dir_module . 'tmp';
@rmdir($tmp);
return parent::uninstall();
}
// Hook appelé pour ajouter le menu
public function hookNFMenu($hookmenu)
{
// Ajoute le lien dans le menu latéral
$html = '<li><a href="index.php?controller=' . $this->modulename . '" title="Génération PDF">PDF Generator</a></li>';
return $html;
}
}
new PdfGenerator();
$PdfGenerator->install();

Remarque : Le code ci‑dessus suit le pattern Dolibarr Module API. Dans une implémentation réelle, vous implémenterez les méthodes getHead, getCSS, getJS si vous avez besoin de ressources spécifiques.


5️⃣ Intégration avec les modèles Dolibarr

Pour que le module PDF Generator soit réellement utile, vous devez savoir quels objets Dolibarr appeler : factures, devis, commandes, contrats, etc.

5.1 Exemple : Générer le PDF d’une facture

use Dolibarr\Models\Facture;
// 1️⃣ Charger la facture n°123
$facture = Facture::fetchByPCP(123, $db); // Retourne un objet Facture ou null
if (!$facture) {
dol_error('Facture introuvable');
}
// 2️⃣ Récupérer les lignes et le tableau de regroupement
$lines = $facture->getLines();
// 3️⃣ Préparer les données pour le template HTML
$data_template = [
'company_name' => $facture->societe->name,
'address' => $facture->societe->address,
'invoice_number' => $facture->num,
'invoice_date' => $facture->datec,
'client_name' => $facture->client->name,
'lines' => $lines,
'total_ht' => $facture->total_ht,
'total_ttc' => $facture->total_ttc
];
// 4️⃣ Point d’entrée du contrôleur (dans pdfgen/class/Controller.php)
$pdfPath = (new \PdfGenerator\PdfGenerator())->generate($data_template, $this->moduleDir.'template/invoice.html');

5.2 Template invoice.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
/* Styles très simples, vous pouvez les enrichir */
table { width: 100%; border-collapse: collapse; }
th, td { border: 1px solid #ddd; padding: 5px; }
th { background-color: #f2f2f2; }
</style>
</head>
<body>
<h1>{{company_name}} – Facture n°{{invoice_number}}</h1>
<p>Date : {{invoice_date}}</p>
<table>
<thead>
<tr>
<th>Désignation</th><th>Qté</th><th>PU (HT)</th><th>Total HT</th>
</tr>
</thead>
<tbody>
{foreach $lines as $line}
<tr>
<td>{$line->label}</td>
<td>{$line->qty}</td>
<td>{$line->unit_price}</td>
<td>{$line->total_discounted}</td>
</tr>
{/foreach}
</tbody>
<tfoot>
<tr><td colspan="3"><strong>Total HT :</strong> {{total_ht}} €</td></tr>
<tr><td colspan="3"><strong>TVA ({{facture->tvainterne}}) :</strong> {{total_ttc - total_ht}} €</td></tr>
<tr><td colspan="3"><strong>TTC :</strong> {{total_ttc}} €</td></tr>
</tfoot>
</table>
</body>
</html>

Note : Le moteur de template utilisé par Dolibarr (<<<template engine interno) accepte les balises {foreach} et {if}. Vous pouvez donc les exploiter dans le fichier invoice.html sans écrire de PHP manuel.


6️⃣ Tests & Validation | Phase | Tests à réaliser | Outils |

|——-|——————|——–|
| Unitaires | Vérifier que le générateur de PDF renvoie un fichier non vide, que le template est correctement injecté. | PHPUnit,Mockery |
| Intégration | Générer un PDF à partir d’une facture réelle, ouvrir le PDF (ou le convertir en image) pour vérifier le rendu. | file_get_contents($pdfPath), Shell::exec('convert …') |
| Performance | Mesurer le temps de génération (max 2 s sur 1000 factures simulées). | microtime(true) |
| Sécurité | S’assurer que les utilisateurs non‑admin ne peuvent pas appeler le contrôleur directement. | Vérification des droits via $user->hasRight('pdfgen','read'). |


7️⃣ Documentation & Packaging

  1. README.md – Sections : Installation, Configuration, Utilisation, FAQ, Changelog.
  2. Guide d’utilisateur (PDF) – Étapes pas‑à‑pas pour créer un PDF via le menu.
  3. Versioning – Tag Git v1.0.0, push du tag sur le repo : git tag -a v1.0.0 -m "First stable PDF Generator" et git push --tags.
  4. Packaging – Créez un zip conforme à Dolibarr (manifest.xml + dossiers) et déposez‑le sur le App Store ou partagez‑le via votre dépôt interne.


8️⃣ Résumé du road‑map en 30 jours | Jour | Action principale | Résultat attendu |

|——|——————-|——————|
| 1‑3 | Installation de Docker, création du repo | Environnement fonctionnel, README installé |
| 4‑7 | Création du module (manifest, hook) | Menu « PDF Generator » visible |
| 8‑12| Intégration de FPDF/Dompdf, création du fichier template | Première fonction generate() fonctionnelle |
| 13‑16| Connexion aux modèles (Facture, Client) | Génération de PDF à partir d’une facture réelle |
| 17‑20| Tests unitaires et d’intégration | 100 % de couverture des fonctions clés |
| 21‑24| Optimisation de la vitesse, ajout de logs | Temps moyen < 1,5 s, logs clairs |
| 25‑27| Rédaction de la documentation et packaging | Zippé pdfgen-1.0.0.zip prêt à être installé |
| 28‑30| Déploiement en pré‑production, validation client | Retour d’utilisateur, possibilité de publier正式版 |


9️⃣ Bonnes pratiques pour la suite

  • Versionner les templates : placez-les dans un sous‑dossier templates/ du module, ajoutez un système de version (ex : v2025-10-01).
  • Gestion multi‑devise : utilisez les fonctions de conversion de Dolibarr ($object->price déjà formatées).
  • Intégration CI/CD : GitHub Actions → phpunit, phpcs, phpmd.
  • Sécurité : toujours filtrer les entrées et vérifier les droits d’accès ($user->hasRight).
  • Extensibilité : exposez des hooks personnalisés (hookNF après génération PDF) afin que d’autres modules puissent réagir (ex : stocker le PDF dans une table pdf_docs).


✅ Conclusion

En 30 jours, il est possible de :

  1. Comprendre l’architecture modulaire de Dolibarr (core + modules + hooks).
  2. Construire un module dédié à la génération de PDF (intégration de FPDF/Dompdf, point d’entrée menu, hooks).
  3. Connecter les données métier (factures, devis, clients) aux templates HTML et les rendre exportables.
  4. Tester, documenter et packager le tout pour le rendre réutilisable par d’autres instances.

Ce parcours vous donne une base solide pour transformer Dolibarr en une plateforme de génération de PDF automatisée, prête à être enrichie (QR‑code, signatures électroniques, batch processing, etc.) à chaque nouveau sprint.

Prochaine étape : ajouter les fonctionnalités avancées (compression, stockage dans la base, accès multi‑utilisateurs) et publier le module sur le Marketplace Dolibarr.

Bon codage ! 🚀

Publications similaires