Corriger l'erreur getIdProductAttributesByIdAttributes sur PrestaShop
Résolvez l'exception fatale getIdProductAttributesByIdAttributes qui bloque vos déclinaisons PrestaShop. Override complet, diagnostic et bonnes pratiques.
En bref : L'erreur 500 sur les déclinaisons PrestaShop provient de la méthode getIdProductAttributeByIdAttributes() qui lève une exception au lieu de gérer gracieusement les combinaisons manquantes. La solution : un override résilient de Product.php qui retourne 0, combiné à un nettoyage des entrées orphelines en base de données.
Le symptôme : une erreur 500 inexplicable sur les fiches produit
Vous naviguez sur votre boutique PrestaShop, vous sélectionnez une déclinaison sur une fiche produit et — écran blanc, erreur 500. Le back-office fonctionne, les autres pages aussi, mais dès qu'un visiteur tente de choisir une combinaison de taille ou de couleur, tout s'effondre.
Le coupable est souvent la méthode getIdProductAttributesByIdAttributes() de la classe Product, qui lève une exception fatale quand elle ne trouve pas la correspondance en base de données entre un produit et ses attributs.
Activer le mode debug pour identifier l'erreur
Avant toute intervention, il est indispensable d'activer le mode debug pour obtenir la stack trace complète plutôt qu'un simple écran blanc.
Dans le fichier config/defines.inc.php :
define('_PS_MODE_DEV_', true);
Sur PrestaShop 8.x, vous pouvez également passer par le back-office : Paramètres avancés → Performances → Mode debug.
Une fois activé, l'erreur affichée ressemblera à :
PrestaShopObjectNotFoundException: Product attribute not found
in classes/Product.php at line XXXX
Cette trace vous confirme que c'est bien getIdProductAttributesByIdAttributes() qui lève l'exception.
Comprendre l'origine du problème
La méthode getIdProductAttributesByIdAttributes() interroge la table ps_product_attribute_combination pour retrouver l'identifiant d'une déclinaison à partir d'un produit et d'un groupe d'attributs (taille, couleur, etc.).
Le problème survient dans deux cas principaux :
1. Incohérence en base de données
Une déclinaison a été supprimée manuellement en base, ou un import CSV a créé des attributs orphelins. La table ps_product_attribute_combination ne contient plus la correspondance attendue, mais le front-end tente quand même de la résoudre.
Pour vérifier :
-- Rechercher les combinaisons orphelines
SELECT pac.id_product_attribute, pac.id_attribute
FROM ps_product_attribute_combination pac
LEFT JOIN ps_product_attribute pa
ON pa.id_product_attribute = pac.id_product_attribute
WHERE pa.id_product_attribute IS NULL;
-- Vérifier les déclinaisons d'un produit spécifique
SELECT pa.id_product_attribute, pac.id_attribute, al.name
FROM ps_product_attribute pa
INNER JOIN ps_product_attribute_combination pac
ON pac.id_product_attribute = pa.id_product_attribute
INNER JOIN ps_attribute_lang al
ON al.id_attribute = pac.id_attribute AND al.id_lang = 1
WHERE pa.id_product = 42
ORDER BY pa.id_product_attribute, pac.id_attribute;
2. Override ou module défectueux
Un module tiers a créé un override de Product.php dans /override/classes/Product.php qui redéfinit cette méthode de manière incorrecte, ou qui appelle une signature incompatible avec la version de PrestaShop installée.
Vérifiez l'existence d'un override :
ls -la override/classes/Product.php
Si ce fichier existe, examinez-le attentivement. Sur PrestaShop 8.x, la méthode native s'appelle getIdProductAttributeByIdAttributes() (sans le s après "Attribute"). Une confusion de nommage entre versions peut provoquer l'erreur.
La solution : un override résilient
L'approche recommandée consiste à surcharger la méthode pour qu'elle retourne gracieusement 0 au lieu de lever une exception fatale quand la déclinaison n'est pas trouvée. Cela évite le crash tout en permettant au front-end de gérer le cas.
Créez ou modifiez le fichier override/classes/Product.php :
<?php
/**
* Override Product - Gestion résiliente des déclinaisons
*/
class Product extends ProductCore
{
/**
* Retrouve l'id_product_attribute à partir des id_attribute.
* Retourne 0 au lieu de lever une exception si la combinaison n'existe pas.
*
* @param int $idProduct
* @param array $idAttributes
* @param bool $findBest
* @return int
*/
public static function getIdProductAttributeByIdAttributes($idProduct, $idAttributes, $findBest = false)
{
$idProduct = (int) $idProduct;
if (!is_array($idAttributes) && is_numeric($idAttributes)) {
$idAttributes = [(int) $idAttributes];
}
if (!is_array($idAttributes) || empty($idAttributes)) {
return 0;
}
$idAttributesImploded = implode(',', array_map('intval', $idAttributes));
$nbAttributes = count($idAttributes);
$idProductAttribute = (int) Db::getInstance()->getValue('
SELECT pac.`id_product_attribute`
FROM `' . _DB_PREFIX_ . 'product_attribute_combination` pac
INNER JOIN `' . _DB_PREFIX_ . 'product_attribute` pa
ON pa.id_product_attribute = pac.id_product_attribute
WHERE pa.id_product = ' . $idProduct . '
AND pac.id_attribute IN (' . $idAttributesImploded . ')
GROUP BY pac.id_product_attribute
HAVING COUNT(pac.id_attribute) = ' . $nbAttributes
);
if (empty($idProductAttribute) && $findBest) {
// Recherche de la meilleure correspondance partielle
$idProductAttribute = (int) Db::getInstance()->getValue('
SELECT pac.`id_product_attribute`
FROM `' . _DB_PREFIX_ . 'product_attribute_combination` pac
INNER JOIN `' . _DB_PREFIX_ . 'product_attribute` pa
ON pa.id_product_attribute = pac.id_product_attribute
WHERE pa.id_product = ' . $idProduct . '
AND pac.id_attribute IN (' . $idAttributesImploded . ')
GROUP BY pac.id_product_attribute
ORDER BY COUNT(pac.id_attribute) DESC
LIMIT 1
');
}
return (int) $idProductAttribute;
}
}
Points clés de cet override
- **Validation d'entrée souple** : au lieu de lever une `PrestaShopException` sur un paramètre invalide, on retourne `0`. Le front-end affichera simplement le produit sans déclinaison présélectionnée.
- **Cast systématique** : `array_map('intval', $idAttributes)` protège contre les injections SQL.
- **Clause HAVING** : garantit que toutes les attributs demandés correspondent, pas seulement un sous-ensemble.
- **Mode `findBest`** : permet de retrouver la correspondance partielle la plus proche quand la combinaison exacte n'existe pas.
Après l'override : vider le cache de classes
PrestaShop compile les overrides dans un fichier unique. Après toute modification :
# Supprimer le cache des classes
rm -f var/cache/prod/class_index.php
rm -f var/cache/dev/class_index.php
# Sur PrestaShop 1.7.x
rm -f app/cache/prod/class_index.php
rm -f app/cache/dev/class_index.php
Ou depuis le back-office : Paramètres avancés → Performances → Vider le cache.
Corriger les données en base si nécessaire
Si le diagnostic révèle des entrées orphelines, nettoyez-les :
-- Supprimer les combinaisons orphelines
DELETE pac FROM ps_product_attribute_combination pac
LEFT JOIN ps_product_attribute pa
ON pa.id_product_attribute = pac.id_product_attribute
WHERE pa.id_product_attribute IS NULL;
-- Supprimer les déclinaisons sans combinaison
DELETE pa FROM ps_product_attribute pa
LEFT JOIN ps_product_attribute_combination pac
ON pac.id_product_attribute = pa.id_product_attribute
WHERE pac.id_product_attribute IS NULL;
Important : faites toujours un backup de votre base avant d'exécuter des requêtes DELETE.
Prévenir la récurrence
Pour éviter que ce problème ne revienne :
- **Utilisez l'import natif** pour gérer vos déclinaisons plutôt que des requêtes SQL directes.
- **Auditez vos modules** : un module qui manipule les attributs sans passer par les classes ObjectModel peut créer des incohérences.
- **Mettez en place un cron de vérification** qui détecte les orphelins avant qu'ils ne causent des erreurs visibles :
// Script de vérification à exécuter en cron hebdomadaire
$orphans = Db::getInstance()->executeS('
SELECT pac.id_product_attribute, pac.id_attribute
FROM `' . _DB_PREFIX_ . 'product_attribute_combination` pac
LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute` pa
ON pa.id_product_attribute = pac.id_product_attribute
WHERE pa.id_product_attribute IS NULL
');
if (!empty($orphans)) {
PrestaShopLogger::addLog(
'Combinaisons orphelines détectées : ' . count($orphans),
2 // Severity: Warning
);
}
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.