Forcer l'ID produit lors de la création dans PrestaShop
Comment imposer un id_product spécifique à la création d'un produit PrestaShop. Méthode ObjectModel::add() avec force_id, alternatives SQL et bonnes pratiques.
En bref : Pour forcer un id_product à la création dans PrestaShop, utilisez $product->force_id = true avant add() plutôt que des UPDATE SQL manuels qui oublient des tables et cassent l'intégrité référentielle.
Forcer l'ID produit lors de la création dans PrestaShop
Lors d'une migration de catalogue, d'une synchronisation ERP ou d'un import personnalisé, il est fréquent de devoir créer des produits avec un identifiant précis plutôt que de laisser PrestaShop attribuer un auto-increment. Le réflexe naturel — affecter $product->id_product avant d'appeler add() — ne fonctionne pas. Voici pourquoi, et comment résoudre ce problème proprement.
Pourquoi `$product->id_product = 40` ne fonctionne pas
La classe Product hérite d'ObjectModel, le socle ORM de PrestaShop. Quand on appelle $product->add(), la méthode exécute un INSERT SQL classique. Par défaut, ObjectModel ignore volontairement toute valeur assignée à la clé primaire : il laisse MySQL générer l'auto-increment, puis récupère l'ID via Db::getInstance()->Insert_ID().
Concrètement, dans classes/ObjectModel.php, la méthode add() construit la requête INSERT sans inclure le champ de clé primaire, sauf si on lui indique explicitement de le faire.
// Ce code ne force PAS l'ID — il sera ignoré
$product = new Product();
$product->id = 40;
$product->name = [(int)Configuration::get('PS_LANG_DEFAULT') => 'Mon produit'];
$product->link_rewrite = [(int)Configuration::get('PS_LANG_DEFAULT') => 'mon-produit'];
$product->add(); // L'ID 40 est ignoré, MySQL attribue l'auto-increment
La solution native : le paramètre `force_id`
PrestaShop a prévu ce cas d'usage. La propriété force_id d'ObjectModel, combinée au paramètre $auto_date et $null_values de la méthode add(), permet d'imposer l'identifiant souhaité.
$product = new Product();
$product->force_id = true; // Clé du mécanisme
$product->id = 40; // L'ID qui sera réellement utilisé
$product->active = 1;
$product->name = [
(int)Configuration::get('PS_LANG_DEFAULT') => 'Mon produit'
];
$product->link_rewrite = [
(int)Configuration::get('PS_LANG_DEFAULT') => 'mon-produit'
];
$product->id_category_default = 2;
$product->id_tax_rules_group = 1;
$product->price = 29.90;
if ($product->add()) {
// L'ID 40 est bien celui du produit créé
StockAvailable::setQuantity($product->id, 0, 10);
}
Quand force_id vaut true, ObjectModel inclut la clé primaire dans la requête INSERT. MySQL accepte la valeur à condition qu'elle ne provoque pas de doublon.
Ce qui se passe sous le capot
Dans ObjectModel::add() (fichier classes/ObjectModel.php), le flux est le suivant :
- Si `force_id` est `false` (défaut) : la clé primaire est exclue de l'INSERT
- Si `force_id` est `true` : la clé primaire est incluse dans les champs insérés
- Les tables liées (`_lang`, `_shop`) reçoivent automatiquement le bon ID
- `ps_category_product`
- `ps_product_attribute`
- `ps_product_attribute_combination`
- `ps_stock_available`
- `ps_specific_price`
- `ps_image` et `ps_image_shop`
- `ps_feature_product`
- `ps_cart_product`
- `ps_order_detail`
- `ps_product_carrier`
- `ps_product_tag`
- Et bien d'autres selon les modules installés
- **Migration de boutique** : conserver les ID pour préserver les URLs, les statistiques et les relations commandes/produits
- **Synchronisation ERP** : aligner les ID PrestaShop sur les codes articles de l'ERP
- **Environnement de développement** : reproduire un catalogue de production à l'identique pour déboguer
- **Multi-boutique** : harmoniser les catalogues entre instances
C'est précisément le mécanisme utilisé en interne par l'import CSV natif de PrestaShop lorsqu'on coche l'option « Forcer les ID ».
L'approche SQL directe : pourquoi l'éviter
Une approche de contournement consiste à créer le produit normalement, puis à modifier son ID via des requêtes SQL brutes :
// ⚠️ Approche fragile — à éviter en production
$product->add();
$old_id = $product->id;
$new_id = 40;
$tables = ['product', 'product_lang', 'product_shop'];
foreach ($tables as $table) {
Db::getInstance()->execute(
'UPDATE `' . _DB_PREFIX_ . $table . '` SET id_product = ' . (int)$new_id .
' WHERE id_product = ' . (int)$old_id
);
}
Cette méthode pose plusieurs problèmes majeurs :
Tables oubliées
Un produit PrestaShop est référencé dans plus de 20 tables. Mettre à jour uniquement product, product_lang et product_shop laisse des orphelins dans :
Contraintes de clé étrangère
Sur PrestaShop 8.x avec InnoDB, certaines tables utilisent des contraintes FOREIGN KEY. Modifier un ID sans respecter l'ordre de mise à jour provoque des erreurs d'intégrité référentielle.
Cache et index de recherche
L'ancien ID reste potentiellement en cache (Smarty, Redis, module de recherche). Le produit devient introuvable ou pointe vers une fiche fantôme.
Bonnes pratiques pour les imports avec ID forcé
1. Vérifier la disponibilité de l'ID
function isProductIdAvailable(int $id_product): bool
{
return !(bool)Db::getInstance()->getValue(
'SELECT COUNT(*) FROM `' . _DB_PREFIX_ . 'product` WHERE id_product = ' . (int)$id_product
);
}
2. Gérer l'auto-increment après import
Après avoir inséré des produits avec des ID imposés, l'auto-increment MySQL peut se retrouver inférieur au plus grand ID inséré. Cela provoquera un conflit lors de la prochaine création sans force_id.
-- Réaligner l'auto-increment après un import forcé
ALTER TABLE ps_product AUTO_INCREMENT = 1;
MySQL recalculera automatiquement la valeur à MAX(id_product) + 1.
3. Encapsuler dans une transaction
Pour un import massif, encapsulez le tout dans une transaction afin de pouvoir annuler proprement en cas d'erreur :
Db::getInstance()->execute('START TRANSACTION');
try {
foreach ($products_to_import as $data) {
$product = new Product();
$product->force_id = true;
$product->id = (int)$data['id_product'];
$product->name = $data['name'];
$product->link_rewrite = $data['link_rewrite'];
// ... autres champs
if (!$product->add()) {
throw new PrestaShopException(
'Échec création produit ID ' . $data['id_product']
);
}
}
Db::getInstance()->execute('COMMIT');
} catch (Exception $e) {
Db::getInstance()->execute('ROLLBACK');
PrestaShopLogger::addLog($e->getMessage(), 3);
}
4. Invalider les caches après import
// Vider le cache produit après un import massif
Cache::clean('Product::*');
Media::clearCache();
Tools::generateHtaccess();
Cas d'usage légitimes
Forcer l'ID produit se justifie dans ces situations :
En dehors de ces cas, laissez PrestaShop gérer ses auto-increments. Forcer des ID sans raison ajoute de la complexité sans bénéfice.
Évolution selon les versions
Le mécanisme force_id est stable depuis PrestaShop 1.5 et reste la méthode officielle sur toutes les versions actuelles.
Questions fréquentes
Tout ce que vous devez savoir sur ce sujet.
Un projet PrestaShop ?
Discutons-en directement.
193 projets livrés
Lire sur le blog

Alexandre Carette
Expert PrestaShop & Architecture E-commerce
Développeur PrestaShop depuis 2014, 193 projets livrés. Je conçois des architectures headless Nuxt + PrestaShop et des outils d'automatisation IA pour les e-commerçants.