Mis à jour le 1er novembre 2026. Article réécrit : la surcharge de 2016 est remplacée par un module qui utilise le hook
actionGenerateDocumentReference, vérifié dans le code de PrestaShop 8.2 et 9.2. Ajout d’une variante séquentielle et d’une section sur le numéro de facture.
Par défaut, PrestaShop attribue à chaque commande une référence de neuf lettres majuscules, par exemple KHWLILZLL. Au téléphone, ce format complique les échanges : quand un client dicte sa référence au service après-vente, le doute s’installe vite entre « B comme Bernard » et « D comme Daniel ». Une référence composée uniquement de chiffres, par exemple 847291536, se dicte et se saisit plus facilement.
En 2016, il fallait surcharger la classe Order. Les versions récentes prévoient un hook : un petit module suffit. Cet article décrit ce module, une variante séquentielle, les endroits où la référence apparaît et la différence avec le numéro de facture.
Comment PrestaShop génère la référence
La référence est produite par la méthode statique Order::generateReference(), dans classes/order/Order.php. Voici son contenu dans PrestaShop 9.2.0, identique dans la branche 8.2 :
public static function generateReference()
{
$reference = Hook::exec('actionGenerateDocumentReference', [
'type' => 'order',
]);
return !empty($reference) ? $reference : strtoupper(Tools::passwdGen(9, 'NO_NUMERIC'));
}
Si un module renvoie une valeur non vide par le hook, elle sert de référence ; sinon, PrestaShop génère neuf caractères sans chiffre. L’unicité est contrôlée dans PaymentModule::validateOrder() : une boucle rappelle generateReference() tant que Order::getByReference() trouve une commande portant cette référence. Le module n’a donc pas à vérifier les doublons.
Ce comportement dépend de la version :
| Version | Hook actionGenerateDocumentReference | Boucle d’unicité dans validateOrder() | Colonne orders.reference |
|---|---|---|---|
| 1.6.1.24 | Absent : la méthode renvoie directement la chaîne aléatoire | Non vérifié | Non vérifié |
| 8.2.x | Présent | Présente | VARCHAR(9) |
| 9.2.0 | Présent | Présente | varchar(255) |
Les lignes 1.6.1.24 et 8.2.x proviennent du dépôt officiel de PrestaShop sur GitHub, la ligne 9.2.0 d’une installation locale. Pour les versions 1.7.x, vérifiez le contenu de generateReference() dans votre propre code avant de choisir la méthode.
Pourquoi un module plutôt qu’une surcharge
La documentation développeur de PrestaShop présente les surcharges comme risquées : elles sont exclusives, déconseillées dans un module destiné à être distribué et interdites dans les modules partenaires. Un hook n’a pas ces inconvénients.
| Critère | Module avec hook | Surcharge de Order |
|---|---|---|
| Fichiers du cœur touchés | Aucun | Aucun, mais la méthode du cœur est remplacée |
| Conflit avec un autre module | Possible si deux modules répondent au hook | Possible si un autre module surcharge Order |
| Désactivation | Désactiver le module | Supprimer le fichier et régénérer l’index des classes |
| Mise à jour de PrestaShop | Le hook continue d’être appelé | La surcharge masque les évolutions de la méthode |
| Disponible sur 1.6.1.24 | Non | Oui |
Étape 1 : créer le module
Créez le dossier modules/numref/ et le fichier modules/numref/numref.php :
<?php
if (!defined('_PS_VERSION_')) {
exit;
}
class Numref extends Module
{
public function __construct()
{
$this->name = 'numref';
$this->tab = 'administration';
$this->version = '1.0.0';
$this->author = 'Votre agence';
$this->need_instance = 0;
$this->ps_versions_compliancy = ['min' => '8.0.0', 'max' => _PS_VERSION_];
parent::__construct();
$this->displayName = $this->trans('Numeric order reference', [], 'Modules.Numref.Admin');
$this->description = $this->trans('Generates 9-digit order references.', [], 'Modules.Numref.Admin');
}
public function install()
{
return parent::install()
&& $this->registerHook('actionGenerateDocumentReference');
}
public function hookActionGenerateDocumentReference(array $params)
{
if (($params['type'] ?? null) !== 'order') {
return '';
}
return (string) random_int(100000000, 999999999);
}
}
Quelques points sur ce code :
random_int(100000000, 999999999)produit un nombre d’exactement neuf chiffres, sans zéro en tête. Il tient dans la colonneVARCHAR(9)de PrestaShop 8.2.- Le hook reçoit un paramètre
type. Le cœur l’appelle avecorder; le test permet d’ignorer d’autres types de documents si un module tiers appelle ce même hook. - Renvoyer une chaîne vide laisse PrestaShop appliquer son format natif, grâce au test
!empty($reference). - Dans
Hook::exec(), les réponses des modules accrochés à un même hook d’action sont concaténées. Un seul module doit donc répondre àactionGenerateDocumentReference, sinon la référence devient la juxtaposition de plusieurs valeurs.
Étape 2 : installer et tester
- Sauvegardez la base de données et les fichiers de la boutique.
- Compressez le dossier
numrefennumref.zip, puis installez-le depuis la page de gestion des modules du back-office. Vous pouvez aussi copier le dossier dansmodules/et l’installer depuis la même page. - Passez une commande de test sur une préproduction. La référence affichée dans le back-office et dans l’e-mail de confirmation doit comporter neuf chiffres.
- En cas d’erreur, activez le mode débogage avec
php bin/console prestashop:debug onet lisez le journal du jour,var/logs/prod-AAAA-MM-JJ.log. Les étapes sont détaillées dans l’activation du mode débogage de PrestaShop et les causes d’une erreur 500. Désactivez ensuite le mode avecprestashop:debug off.
Pour revenir au format natif, désactivez le module.
Variante : une numérotation séquentielle
Certains marchands préfèrent des références qui se suivent. L’erreur classique consiste à calculer MAX(id_order) + 1 : deux commandes validées au même moment peuvent obtenir le même numéro. Une table avec une colonne AUTO_INCREMENT règle ce problème, car MySQL attribue chaque valeur une seule fois, même en cas d’accès simultanés. Remplacez les méthodes install() et hookActionGenerateDocumentReference() du module par :
<?php
class Numref extends Module
{
public function install()
{
return parent::install()
&& Db::getInstance()->execute('CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'numref_sequence` (
`id_sequence` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`date_add` DATETIME NOT NULL,
PRIMARY KEY (`id_sequence`)
) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8mb4')
&& $this->registerHook('actionGenerateDocumentReference');
}
public function hookActionGenerateDocumentReference(array $params)
{
if (($params['type'] ?? null) !== 'order') {
return '';
}
$db = Db::getInstance();
if (!$db->insert('numref_sequence', ['date_add' => date('Y-m-d H:i:s')])) {
return '';
}
return (string) (100000000 + (int) $db->Insert_ID());
}
}
Le décalage de 100 000 000 garantit neuf chiffres dès la première commande. Ne supprimez pas la table à la désinstallation : une réinstallation repartirait de zéro. La séquence peut comporter des trous, par exemple si une validation échoue après la génération : c’est sans conséquence pour une référence de commande, qui n’est pas une pièce comptable.
| Format | Avantage | Limite |
|---|---|---|
| Natif, neuf lettres | Aucun développement | Difficile à dicter |
| Neuf chiffres aléatoires | Facile à dicter, ne révèle pas le volume de commandes | Collisions possibles, écartées par la boucle du cœur |
| Neuf chiffres séquentiels | Ordre chronologique lisible | Révèle le nombre de commandes et rend les références voisines prévisibles |
Le risque de collision des références aléatoires
Neuf chiffres aléatoires offrent 900 millions de valeurs, mais les doublons arrivent tôt (paradoxe des anniversaires). Le nombre moyen de paires identiques vaut environ n² divisé par deux fois le nombre de valeurs, n étant le nombre de commandes : environ 0,06 à 10 000 commandes, 5,6 à 100 000. Sur 8.2 et 9.2, la boucle de validateOrder() écarte ces doublons. Reste le cas, très improbable, de deux commandes validées au même instant avec la même valeur. Une contrainte d’unicité le fermerait, mais elle modifierait une table du cœur et bloquerait les commandes multiples d’un même panier, qui partagent la référence.
Où la référence apparaît
- E-mails : la variable
{order_name}utiliseOrder::getUniqReference(). Quand un panier donne plusieurs commandes, par exemple pour plusieurs transporteurs, elles partagent la même référence et l’e-mail ajoute un suffixe :847291536#1,847291536#2. - Suivi de commande invité : le contrôleur
GuestTrackingControllerretrouve la commande avec la référence et l’adresse e-mail. Avec des références séquentielles, l’e-mail reste le seul élément difficile à deviner. - Modules de paiement et de transport : vérifiez qu’ils acceptent une référence purement numérique.
- Anciennes commandes : elles gardent leur référence, déjà présente sur des documents envoyés ; ne la modifiez pas.
Référence de commande et numéro de facture
La référence de commande n’est pas le numéro de facture. Le numéro de facture est stocké dans la colonne number de la table order_invoice, sous forme d’entier, et son affichage est réglé dans Commandes > Factures :
| Réglage du back-office | Clé de configuration | Effet |
|---|---|---|
| Préfixe de facture | PS_INVOICE_PREFIX | Texte placé avant le numéro, par langue |
| Ajouter l’année courante au numéro de facture | PS_INVOICE_USE_YEAR | Ajoute l’année au numéro affiché |
| Position de l’année | PS_INVOICE_YEAR_POS | Avant ou après le numéro séquentiel |
| Réinitialiser le numéro de facture au début de chaque année | PS_INVOICE_RESET | Repart de 1 chaque année |
| Numéro de facture | PS_INVOICE_START_NUMBER | Numéro de la prochaine facture, effacé une fois utilisé |
Le format par défaut, défini dans OrderInvoice::getInvoiceNumberFormatted(), est le préfixe suivi du numéro sur six chiffres. En France, le numéro de facture doit reposer sur une séquence chronologique et continue, selon la fiche officielle sur les mentions obligatoires. Toute modification de la numérotation se décide donc avec un expert-comptable.
Pour un format d’affichage que les réglages ne permettent pas, PrestaShop 9.2 appelle le hook actionInvoiceNumberFormatted avant d’appliquer son format. Il reçoit l’objet facture, la langue, la boutique et le numéro. Ajoutez au module la méthode suivante et enregistrez le hook dans install() :
<?php
class Numref extends Module
{
public function hookActionInvoiceNumberFormatted(array $params)
{
$invoice = $params['OrderInvoice'] ?? null;
if (!$invoice instanceof OrderInvoice) {
return '';
}
return sprintf('F%s-%06d', date('Y', strtotime($invoice->date_add)), (int) $params['number']);
}
}
Ce hook ne change que l’affichage : la séquence des numéros reste gérée par le cœur. Limite constatée dans le code : la recherche d’une facture par son numéro formaté, dans OrderInvoice::getInvoiceByNumber(), ne reconnaît que le préfixe configuré suivi de chiffres. Avec un format personnalisé, recherchez par le numéro seul.
Cas de PrestaShop 1.6 : la surcharge
Sur PrestaShop 1.6.1.24, generateReference() n’appelle aucun hook. La surcharge reste la seule option. Créez override/classes/order/Order.php :
<?php
class Order extends OrderCore
{
public static function generateReference()
{
do {
$reference = (string) random_int(100000000, 999999999);
} while ((int) Db::getInstance()->getValue(
'SELECT COUNT(*) FROM `' . _DB_PREFIX_ . 'orders` WHERE `reference` = \'' . pSQL($reference) . '\''
) > 0);
return $reference;
}
}
La boucle vérifie l’unicité, car le contrôle de validateOrder() n’a pas été vérifié pour la 1.6. random_int() exige PHP 7.0 ou plus. Supprimez ensuite cache/class_index.php pour qu’il soit régénéré. Sur 8 et 9, cet index se trouve dans var/cache/prod/class_index.php, et Paramètres avancés > Performances permet de désactiver toutes les surcharges pour un diagnostic. En migrant vers une version récente, remplacez la surcharge par le module, en suivant la mise à jour sécurisée de PrestaShop sur un VPS.
La structure complète d’un module plus riche (table, contrôleur, commande console) est détaillée dans la création d’un module PrestaShop connecté à une API d’IA. Si vous préférez un module livré et testé sur votre version, l’agence Genisoft peut le développer : décrivez votre besoin dans notre formulaire de demande de développement sur mesure.
Questions fréquentes
La référence de commande et le numéro de facture sont-ils identiques ?
Non. La référence identifie la commande et se règle par le hook actionGenerateDocumentReference. Le numéro de facture est un entier séquentiel de la table order_invoice, réglé dans Commandes > Factures, dont seul l’affichage peut être adapté par actionInvoiceNumberFormatted.
Puis-je modifier les références des commandes déjà passées ?
Ce tutoriel ne le recommande pas : elles figurent dans des e-mails et des documents déjà envoyés. Les conséquences comptables d’une telle opération doivent être validées avec un expert-comptable.
Le module fonctionne-t-il sur PrestaShop 9 ?
Le code a été vérifié contre les sources de PrestaShop 9.2.0 : nom du hook, paramètre type, traitement de la valeur renvoyée et boucle d’unicité. Testez-le néanmoins sur une préproduction avec vos modules de paiement avant la mise en production.
Puis-je utiliser plus de neuf chiffres ?
Sur PrestaShop 9.2, la colonne accepte 255 caractères. Sur PrestaShop 8.2, elle est limitée à neuf : une référence plus longue serait tronquée ou refusée selon le mode SQL du serveur. Vérifiez la définition de la colonne reference de la table orders de votre boutique avant d’allonger le format.
Sources
- Code source de PrestaShop 9.2.0 (installation locale) :
classes/order/Order.php(generateReference(),getUniqReference(),setLastInvoiceNumber()),classes/PaymentModule.php,classes/Hook.php,classes/order/OrderInvoice.php,controllers/front/GuestTrackingController.php,src/PrestaShopBundle/Form/Admin/Sell/Order/Invoices/InvoiceOptionsType.php, structure de la tableorders. - PrestaShop, branche 8.2.x sur GitHub :
classes/order/Order.php,classes/PaymentModule.php,install-dev/data/db_structure.sql. - PrestaShop, version 1.6.1.24 sur GitHub :
classes/order/Order.php. - PrestaShop DevDocs, hook actionGenerateDocumentReference : https://devdocs.prestashop-project.org/9/modules/concepts/hooks/list-of-hooks/actiongeneratedocumentreference/
- PrestaShop DevDocs, Hooks : https://devdocs.prestashop-project.org/9/modules/concepts/hooks/
- PrestaShop DevDocs, Overrides : https://devdocs.prestashop-project.org/9/modules/concepts/overrides/
- Entreprendre.Service-Public, « Mentions obligatoires sur une facture » (vérifié le 11 août 2026) : https://entreprendre.service-public.gouv.fr/vosdroits/F31808