[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"theme-db":3,"$fa4FwZv0AnmfSY7d4ObFMwT9FnKxMi060tKF1OjbVlYI":22,"megamenu":59,"$fKnz2vuX4bZz1LbUTiuFsvSZ3e07l5_5fqNYp4Tzdhi8":128,"footer-db":196,"$fdEEmeO1Y09RB6LJyiexHsPb6ZUl7f2JePql8jmmFSBA":214,"header-db":228},{"theme":4},{"colors":5,"typography":13,"ui":17,"defaultColorMode":21},{"primary":6,"secondary":7,"background":8,"foreground":9,"muted":10,"headerBg":11,"footerBg":12,"topBarBg":9,"topBarText":11},"#4F46E5","#0D9488","#F9FAFB","#111827","#6B7280","#ffffff","#020617",{"fontFamily":14,"fontUrl":15,"baseFontSize":16},"Inter, system-ui, sans-serif","https:\u002F\u002Ffonts.googleapis.com\u002Fcss2?family=Inter:wght@400;500;600;700&family=Playfair+Display:ital,wght@0,400;0,700;0,800;0,900;1,400;1,700&display=swap","16px",{"borderRadius":18,"contentWidth":19,"shadow":20},"lg","7xl",true,"light",{"title":23,"slug":24,"metaDescription":25,"category":26,"tags":27,"difficulty":33,"psVersions":34,"content":37,"faq":38,"tldr":54,"readingTime":55,"generatedAt":56,"publishDate":56,"relatedArticles":57,"sourceCategory":58},"Corriger l'erreur getIdProductAttributesByIdAttributes sur PrestaShop","corriger-erreur-getidproductattributesbyidattributes-prestashop","Résolvez l'exception fatale getIdProductAttributesByIdAttributes qui bloque vos déclinaisons PrestaShop. Override complet, diagnostic et bonnes pratiques.","debug",[28,29,30,31,32],"déclinaisons","override","Product.php","erreur 500","product_attribute_combination","intermediaire",[35,36],"1.7","8.x","\u003Ch2>Le symptôme : une erreur 500 inexplicable sur les fiches produit\u003C\u002Fh2>\n\u003Cp>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.\u003C\u002Fp>\n\u003Cp>Le coupable est souvent la méthode \u003Ccode>getIdProductAttributesByIdAttributes()\u003C\u002Fcode> de la classe \u003Ccode>Product\u003C\u002Fcode>, qui lève une exception fatale quand elle ne trouve pas la correspondance en base de données entre un produit et ses attributs.\u003C\u002Fp>\n\u003Ch2>Activer le mode debug pour identifier l'erreur\u003C\u002Fh2>\n\u003Cp>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.\u003C\u002Fp>\n\u003Cp>Dans le fichier \u003Ccode>config\u002Fdefines.inc.php\u003C\u002Fcode> :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">\ndefine('_PS_MODE_DEV_', true);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Sur PrestaShop 8.x, vous pouvez également passer par le back-office : \u003Cstrong>Paramètres avancés → Performances → Mode debug\u003C\u002Fstrong>.\u003C\u002Fp>\n\u003Cp>Une fois activé, l'erreur affichée ressemblera à :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-\">\nPrestaShopObjectNotFoundException: Product attribute not found\nin classes\u002FProduct.php at line XXXX\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Cette trace vous confirme que c'est bien \u003Ccode>getIdProductAttributesByIdAttributes()\u003C\u002Fcode> qui lève l'exception.\u003C\u002Fp>\n\u003Ch2>Comprendre l'origine du problème\u003C\u002Fh2>\n\u003Cp>La méthode \u003Ccode>getIdProductAttributesByIdAttributes()\u003C\u002Fcode> interroge la table \u003Ccode>ps_product_attribute_combination\u003C\u002Fcode> pour retrouver l'identifiant d'une déclinaison à partir d'un produit et d'un groupe d'attributs (taille, couleur, etc.).\u003C\u002Fp>\n\u003Cp>Le problème survient dans deux cas principaux :\u003C\u002Fp>\n\u003Ch3>1. Incohérence en base de données\u003C\u002Fh3>\n\u003Cp>Une déclinaison a été supprimée manuellement en base, ou un import CSV a créé des attributs orphelins. La table \u003Ccode>ps_product_attribute_combination\u003C\u002Fcode> ne contient plus la correspondance attendue, mais le front-end tente quand même de la résoudre.\u003C\u002Fp>\n\u003Cp>Pour vérifier :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-sql\">\n-- Rechercher les combinaisons orphelines\nSELECT pac.id_product_attribute, pac.id_attribute\nFROM ps_product_attribute_combination pac\nLEFT JOIN ps_product_attribute pa\n  ON pa.id_product_attribute = pac.id_product_attribute\nWHERE pa.id_product_attribute IS NULL;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cpre>\u003Ccode class=\"language-sql\">\n-- Vérifier les déclinaisons d'un produit spécifique\nSELECT pa.id_product_attribute, pac.id_attribute, al.name\nFROM ps_product_attribute pa\nINNER JOIN ps_product_attribute_combination pac\n  ON pac.id_product_attribute = pa.id_product_attribute\nINNER JOIN ps_attribute_lang al\n  ON al.id_attribute = pac.id_attribute AND al.id_lang = 1\nWHERE pa.id_product = 42\nORDER BY pa.id_product_attribute, pac.id_attribute;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>2. Override ou module défectueux\u003C\u002Fh3>\n\u003Cp>Un module tiers a créé un override de \u003Ccode>Product.php\u003C\u002Fcode> dans \u003Ccode>\u002Foverride\u002Fclasses\u002FProduct.php\u003C\u002Fcode> qui redéfinit cette méthode de manière incorrecte, ou qui appelle une signature incompatible avec la version de PrestaShop installée.\u003C\u002Fp>\n\u003Cp>Vérifiez l'existence d'un override :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">\nls -la override\u002Fclasses\u002FProduct.php\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Si ce fichier existe, examinez-le attentivement. Sur PrestaShop 8.x, la méthode native s'appelle \u003Ccode>getIdProductAttributeByIdAttributes()\u003C\u002Fcode> (sans le \u003Cstrong>s\u003C\u002Fstrong> après \"Attribute\"). Une confusion de nommage entre versions peut provoquer l'erreur.\u003C\u002Fp>\n\u003Ch2>La solution : un override résilient\u003C\u002Fh2>\n\u003Cp>L'approche recommandée consiste à surcharger la méthode pour qu'elle retourne gracieusement \u003Ccode>0\u003C\u002Fcode> 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.\u003C\u002Fp>\n\u003Cp>Créez ou modifiez le fichier \u003Ccode>override\u002Fclasses\u002FProduct.php\u003C\u002Fcode> :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">\n&lt;?php\n\u002F**\n * Override Product - Gestion résiliente des déclinaisons\n *\u002F\nclass Product extends ProductCore\n{\n    \u002F**\n     * Retrouve l'id_product_attribute à partir des id_attribute.\n     * Retourne 0 au lieu de lever une exception si la combinaison n'existe pas.\n     *\n     * @param int $idProduct\n     * @param array $idAttributes\n     * @param bool $findBest\n     * @return int\n     *\u002F\n    public static function getIdProductAttributeByIdAttributes($idProduct, $idAttributes, $findBest = false)\n    {\n        $idProduct = (int) $idProduct;\n\n        if (!is_array($idAttributes) && is_numeric($idAttributes)) {\n            $idAttributes = [(int) $idAttributes];\n        }\n\n        if (!is_array($idAttributes) || empty($idAttributes)) {\n            return 0;\n        }\n\n        $idAttributesImploded = implode(',', array_map('intval', $idAttributes));\n        $nbAttributes = count($idAttributes);\n\n        $idProductAttribute = (int) Db::getInstance()-&gt;getValue('\n            SELECT pac.`id_product_attribute`\n            FROM `' . _DB_PREFIX_ . 'product_attribute_combination` pac\n            INNER JOIN `' . _DB_PREFIX_ . 'product_attribute` pa\n                ON pa.id_product_attribute = pac.id_product_attribute\n            WHERE pa.id_product = ' . $idProduct . '\n                AND pac.id_attribute IN (' . $idAttributesImploded . ')\n            GROUP BY pac.id_product_attribute\n            HAVING COUNT(pac.id_attribute) = ' . $nbAttributes\n        );\n\n        if (empty($idProductAttribute) && $findBest) {\n            \u002F\u002F Recherche de la meilleure correspondance partielle\n            $idProductAttribute = (int) Db::getInstance()-&gt;getValue('\n                SELECT pac.`id_product_attribute`\n                FROM `' . _DB_PREFIX_ . 'product_attribute_combination` pac\n                INNER JOIN `' . _DB_PREFIX_ . 'product_attribute` pa\n                    ON pa.id_product_attribute = pac.id_product_attribute\n                WHERE pa.id_product = ' . $idProduct . '\n                    AND pac.id_attribute IN (' . $idAttributesImploded . ')\n                GROUP BY pac.id_product_attribute\n                ORDER BY COUNT(pac.id_attribute) DESC\n                LIMIT 1\n            ');\n        }\n\n        return (int) $idProductAttribute;\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Points clés de cet override\u003C\u002Fh3>\n\u003Cul>\n\u003Cli>**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.\u003C\u002Fli>\n\u003Cli>**Cast systématique** : `array_map('intval', $idAttributes)` protège contre les injections SQL.\u003C\u002Fli>\n\u003Cli>**Clause HAVING** : garantit que toutes les attributs demandés correspondent, pas seulement un sous-ensemble.\u003C\u002Fli>\n\u003Cli>**Mode `findBest`** : permet de retrouver la correspondance partielle la plus proche quand la combinaison exacte n'existe pas.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>Après l'override : vider le cache de classes\u003C\u002Fh2>\n\u003Cp>PrestaShop compile les overrides dans un fichier unique. Après toute modification :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">\n# Supprimer le cache des classes\nrm -f var\u002Fcache\u002Fprod\u002Fclass_index.php\nrm -f var\u002Fcache\u002Fdev\u002Fclass_index.php\n\n# Sur PrestaShop 1.7.x\nrm -f app\u002Fcache\u002Fprod\u002Fclass_index.php\nrm -f app\u002Fcache\u002Fdev\u002Fclass_index.php\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Ou depuis le back-office : \u003Cstrong>Paramètres avancés → Performances → Vider le cache\u003C\u002Fstrong>.\u003C\u002Fp>\n\u003Ch2>Corriger les données en base si nécessaire\u003C\u002Fh2>\n\u003Cp>Si le diagnostic révèle des entrées orphelines, nettoyez-les :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-sql\">\n-- Supprimer les combinaisons orphelines\nDELETE pac FROM ps_product_attribute_combination pac\nLEFT JOIN ps_product_attribute pa\n  ON pa.id_product_attribute = pac.id_product_attribute\nWHERE pa.id_product_attribute IS NULL;\n\n-- Supprimer les déclinaisons sans combinaison\nDELETE pa FROM ps_product_attribute pa\nLEFT JOIN ps_product_attribute_combination pac\n  ON pac.id_product_attribute = pa.id_product_attribute\nWHERE pac.id_product_attribute IS NULL;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cblockquote>\u003Cp>\u003Cstrong>Important\u003C\u002Fstrong> : faites toujours un backup de votre base avant d'exécuter des requêtes DELETE.\u003C\u002Fp>\u003C\u002Fblockquote>\n\u003Ch2>Prévenir la récurrence\u003C\u002Fh2>\n\u003Cp>Pour éviter que ce problème ne revienne :\u003C\u002Fp>\n\u003Col>\n\u003Cli>**Utilisez l'import natif** pour gérer vos déclinaisons plutôt que des requêtes SQL directes.\u003C\u002Fli>\n\u003Cli>**Auditez vos modules** : un module qui manipule les attributs sans passer par les classes ObjectModel peut créer des incohérences.\u003C\u002Fli>\n\u003Cli>**Mettez en place un cron de vérification** qui détecte les orphelins avant qu'ils ne causent des erreurs visibles :\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cpre>\u003Ccode class=\"language-php\">\n\u002F\u002F Script de vérification à exécuter en cron hebdomadaire\n$orphans = Db::getInstance()-&gt;executeS('\n    SELECT pac.id_product_attribute, pac.id_attribute\n    FROM `' . _DB_PREFIX_ . 'product_attribute_combination` pac\n    LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute` pa\n        ON pa.id_product_attribute = pac.id_product_attribute\n    WHERE pa.id_product_attribute IS NULL\n');\n\nif (!empty($orphans)) {\n    PrestaShopLogger::addLog(\n        'Combinaisons orphelines détectées : ' . count($orphans),\n        2 \u002F\u002F Severity: Warning\n    );\n}\n\u003C\u002Fcode>\u003C\u002Fpre>",[39,42,45,48,51],{"q":40,"a":41},"Pourquoi mes déclinaisons provoquent une erreur 500 sur PrestaShop ?","L'erreur 500 liée aux déclinaisons est généralement causée par la méthode getIdProductAttributeByIdAttributes() qui lève une exception quand elle ne trouve pas la correspondance entre un produit et ses attributs en base de données. Cela arrive suite à une suppression manuelle de déclinaisons, un import CSV incomplet, ou un override défectueux de la classe Product.php.",{"q":43,"a":44},"Comment savoir si un override de Product.php cause le problème de déclinaisons ?","Vérifiez si le fichier override\u002Fclasses\u002FProduct.php existe sur votre installation. Si oui, examinez s'il contient une méthode getIdProductAttributesByIdAttributes(). Attention à la différence de nommage entre versions : sur PrestaShop 8.x, la méthode native est getIdProductAttributeByIdAttributes (sans le 's' après Attribute). Une confusion de nom entre versions est une source fréquente de cette erreur.",{"q":46,"a":47},"Faut-il supprimer ou corriger l'override Product.php sur PrestaShop 8 ?","Il est recommandé de corriger l'override plutôt que de le supprimer, car un module installé peut en dépendre. La bonne approche est de rendre la méthode résiliente en retournant 0 au lieu de lever une exception quand la déclinaison n'est pas trouvée. N'oubliez pas de vider le cache des classes (var\u002Fcache\u002Fprod\u002Fclass_index.php) après toute modification.",{"q":49,"a":50},"Comment détecter les déclinaisons orphelines dans la base PrestaShop ?","Exécutez une requête SQL de jointure entre ps_product_attribute_combination et ps_product_attribute avec un LEFT JOIN. Les lignes où ps_product_attribute.id_product_attribute est NULL sont des combinaisons orphelines qui doivent être nettoyées. Faites toujours un backup complet de la base avant de supprimer ces entrées.",{"q":52,"a":53},"L'override de Product.php est-il compatible avec PrestaShop 1.7 et 8.x ?","Oui, l'override présenté est compatible avec PrestaShop 1.7.x et 8.x. La signature de la méthode et la structure des tables ps_product_attribute et ps_product_attribute_combination sont identiques entre ces versions. Seul le chemin du cache diffère : app\u002Fcache\u002F sur 1.7.x et var\u002Fcache\u002F sur 8.x.","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.",6,"2026-03-21T13:29:42.000Z",[],"PrestaShop pour les développeurs",{"items":60},[61,72,80,88,96,105,113,120],{"id":62,"type":63,"label":64,"href":66,"icon":67,"description":67,"badge":67,"groupTitle":67,"style":67,"gridColumns":67,"cssClass":67,"psCategoryId":67,"showPsChildren":68,"position":69,"children":70,"psChildren":71},41,"link",{"fr":65},"Expertise","\u002Fexpertise",null,false,0,[],[],{"id":73,"type":63,"label":74,"href":76,"icon":67,"description":67,"badge":67,"groupTitle":67,"style":67,"gridColumns":67,"cssClass":67,"psCategoryId":67,"showPsChildren":68,"position":77,"children":78,"psChildren":79},42,{"fr":75},"Blog","\u002Fblog",1,[],[],{"id":81,"type":63,"label":82,"href":84,"icon":67,"description":67,"badge":67,"groupTitle":67,"style":67,"gridColumns":67,"cssClass":67,"psCategoryId":67,"showPsChildren":68,"position":85,"children":86,"psChildren":87},43,{"fr":83},"Modules PrestaShop","\u002Fmodules",2,[],[],{"id":89,"type":63,"label":90,"href":92,"icon":67,"description":67,"badge":67,"groupTitle":67,"style":67,"gridColumns":67,"cssClass":67,"psCategoryId":67,"showPsChildren":68,"position":93,"children":94,"psChildren":95},44,{"fr":91},"Outils IA","\u002Foutils-ia",3,[],[],{"id":97,"type":63,"label":98,"href":100,"icon":67,"description":67,"badge":67,"groupTitle":67,"style":101,"gridColumns":67,"cssClass":67,"psCategoryId":67,"showPsChildren":68,"position":102,"children":103,"psChildren":104},45,{"fr":99},"Offre Starter ✨","\u002Foffre-starter",{"highlight":20},4,[],[],{"id":106,"type":63,"label":107,"href":109,"icon":67,"description":67,"badge":67,"groupTitle":67,"style":67,"gridColumns":67,"cssClass":67,"psCategoryId":67,"showPsChildren":68,"position":110,"children":111,"psChildren":112},46,{"fr":108},"Academy","\u002Facademy",5,[],[],{"id":114,"type":63,"label":115,"href":117,"icon":67,"description":67,"badge":67,"groupTitle":67,"style":67,"gridColumns":67,"cssClass":67,"psCategoryId":67,"showPsChildren":68,"position":55,"children":118,"psChildren":119},47,{"fr":116},"À propos","\u002Fa-propos",[],[],{"id":121,"type":63,"label":122,"href":124,"icon":67,"description":67,"badge":67,"groupTitle":67,"style":67,"gridColumns":67,"cssClass":67,"psCategoryId":67,"showPsChildren":68,"position":125,"children":126,"psChildren":127},48,{"fr":123},"Contact","\u002Fcontact",7,[],[],{"columns":129},[130,142,172,188],{"title":131,"links":132},"Plateforme",[133,135,138,139],{"label":134,"href":100,"external":68},"Offre Starter (2 500 €)",{"label":136,"href":137,"external":68},"Devenir Ambassadeur","\u002Fambassadeur",{"label":83,"href":84,"external":68},{"label":140,"href":141,"external":20},"CodeMyShop.com","https:\u002F\u002Fcodemyshop.com",{"title":143,"links":144},"Le Synedre",[145,148,151,154,157,160,163,166,169],{"label":146,"href":147,"external":68},"L'histoire","\u002Fsynedre",{"label":149,"href":150,"external":68},"Constitution","\u002Fsynedre\u002Fconstitution",{"label":152,"href":153,"external":68},"L'équipe","\u002Fequipe",{"label":155,"href":156,"external":68},"Le réacteur en direct","\u002Freacteur",{"label":158,"href":159,"external":68},"Le Drill (entraînement)","\u002Fdrill",{"label":161,"href":162,"external":68},"Protocole de réunion","\u002Fsynedre\u002Freunion",{"label":164,"href":165,"external":68},"Les agents IA","\u002Fagents-ia",{"label":167,"href":168,"external":68},"La Conduite","\u002Fsynedre\u002Fconduite",{"label":170,"href":171,"external":68},"Charte plateforme","\u002Fsynedre\u002Fcharte",{"title":173,"links":174},"Ressources",[175,176,177,180,182,185],{"label":75,"href":76,"external":68},{"label":108,"href":109,"external":68},{"label":178,"href":179,"external":68},"Dictionnaire","\u002Fdictionnaire",{"label":181,"href":66,"external":68},"Expertise PrestaShop",{"label":183,"href":184,"external":68},"Flywheel","\u002Fflywheel",{"label":186,"href":187,"external":68},"Manifeste","\u002Fmanifeste",{"title":116,"links":189},[190,192,195],{"label":191,"href":117,"external":68},"Alexandre Carette",{"label":193,"href":194,"external":68},"Dossier de presse","\u002Fpresse",{"label":123,"href":124,"external":68},{"footer":197},{"theme":198,"description":67,"hours":67,"logo":199,"contact":202,"social":203,"bottomBar":213},"dark",{"src":200,"href":201,"alt":191},"\u002Flogo-ac.svg","\u002F",{"email":67,"phone":67,"address":67,"cta":67},[204,207,210],{"platform":205,"href":206,"label":205},"linkedin","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Falexandre-carette\u002F",{"platform":208,"href":209,"label":208},"malt","https:\u002F\u002Fwww.malt.fr\u002Fprofile\u002Falexandrecarette",{"platform":211,"href":212,"label":211},"github","https:\u002F\u002Fgithub.com\u002Fprest4cafe",{"copyright":67},{"academy":215,"blog":216,"expertise":227},[],[217,221,224],{"title":218,"url":219,"score":77,"type":220},"PrestaShop headless avec Nuxt 3 : pourquoi séparer back et front","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fprestashop-headless-nuxt-separation-front-back","blog",{"title":222,"url":223,"score":77,"type":220},"PrestaShop headless : Nuxt 3, pas Next.js — le choix souverain","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fprestashop-headless-nuxt-nextjs-souverainete",{"title":225,"url":226,"score":77,"type":220},"Sylius rachète PrestaShop : ce que ça change pour vous","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fsylius-rachat-prestashop-headless-souverainete",[],{"header":229},{"logo":230,"topBar":233,"contactEmail":236,"features":237,"navBar":67},{"src":200,"alt":231,"text":191,"href":201,"class":232},"Alexandre Carette — Architecte E-commerce Souverain","h-10 w-10",{"message":67,"showLanguages":68,"align":234,"languages":235},"left",[],"contact@alexandrecarette.fr",{"showSearch":68,"showWishlist":68,"showLogin":20,"showContact":68,"showCart":68,"stickyHeader":20,"headerLayout":238},"inline"]