🏪 Multi-boutiqueIntermédiaire PS 1.7 PS 8.x

Corriger l'erreur « id_shop n'est pas valide » en multi-boutique PrestaShop

Guide complet pour résoudre l'erreur id_shop invalide en multi-boutique PrestaShop. Diagnostic, création des tables _shop manquantes et correction du modèle ObjectModel.

En bref : L'erreur « id_shop n'est pas valide » survient quand un module PrestaShop ne possède pas de table _shop associative ni la déclaration multishop dans son ObjectModel. La correction implique de créer la table manquante, d'ajouter id_shop dans les tables existantes, et de mettre à jour la définition du modèle PHP.

Publié le 21 mars 2026 6 min de lecture Alexandre Carette

Le problème : un module incompatible multi-boutique

Vous activez le mode multi-boutique de PrestaShop, vous basculez sur un contexte boutique spécifique, et là : « id_shop n'est pas valide ». L'erreur survient systématiquement lorsqu'un module tiers tente d'enregistrer ou de lire des données sans gérer correctement l'association aux boutiques.

Le coupable est presque toujours le même : le développeur du module n'a pas prévu la compatibilité multi-boutique dans sa structure de base de données ni dans son modèle ObjectModel.

Comprendre l'architecture multi-boutique de PrestaShop

PrestaShop repose sur un mécanisme de tables associatives pour isoler les données par boutique. Pour chaque entité compatible multi-boutique, on retrouve généralement trois tables :

TableRôle `ps_mon_entite`Table principale (données communes) `ps_mon_entite_shop`Association entité ↔ boutique `ps_mon_entite_lang`Traductions par langue (et parfois par boutique)

Quand la table _shop est absente, PrestaShop ne peut pas associer l'enregistrement à une boutique. L'ObjectModel lève alors l'erreur id_shop n'est pas valide lors de l'appel à add() ou save().

Diagnostic étape par étape

1. Identifier les tables du module

Ouvrez phpMyAdmin et listez les tables du module concerné :


SHOW TABLES LIKE '%navcmsblock%';

Vous devriez obtenir quelque chose comme :


ps_tmnavcmsblockinfo
ps_tmnavcmsblockinfo_lang

Si vous ne voyez pas de table ps_tmnavcmsblockinfo_shop, c'est la cause du problème.

2. Vérifier la colonne id_shop dans la table principale

Inspectez la structure de la table principale :


DESCRIBE ps_tmnavcmsblockinfo;

Si la colonne id_shop est absente ou mal typée, l'ObjectModel ne peut pas filtrer par boutique.

3. Vérifier le modèle ObjectModel du module

Ouvrez le fichier PHP de la classe du modèle (souvent classes/NavCmsBlock.php ou équivalent) et cherchez la propriété $definition. Un modèle correctement configuré pour le multi-boutique doit contenir :


public static $definition = array(
    'table' => 'tmnavcmsblockinfo',
    'primary' => 'id_tmnavcmsblockinfo',
    'multilang' => true,
    'multishop' => true,  // <-- Souvent absent dans les modules mal codés
    'fields' => array(
        'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
        // ... autres champs
    ),
);

L'absence de 'multishop' => true ou de la déclaration du champ id_shop est un indicateur fiable du problème.

Correction complète

Étape 1 : Créer la table `_shop` manquante

Exécutez cette requête SQL via phpMyAdmin (onglet SQL) :


CREATE TABLE IF NOT EXISTS `ps_tmnavcmsblockinfo_shop` (
    `id_tmnavcmsblockinfo` INT UNSIGNED NOT NULL,
    `id_shop` INT(10) UNSIGNED NOT NULL,
    PRIMARY KEY (`id_tmnavcmsblockinfo`, `id_shop`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Note PrestaShop 8.x : Utilisez utf8mb4 au lieu de utf8 et InnoDB au lieu de la variable _MYSQL_ENGINE_ si vous exécutez la requête manuellement. En PHP, conservez _MYSQL_ENGINE_ pour la portabilité.

Étape 2 : Ajouter id_shop dans la table _lang si nécessaire

Certains modules nécessitent aussi l'association boutique dans la table des traductions :


ALTER TABLE `ps_tmnavcmsblockinfo_lang`
ADD COLUMN `id_shop` INT(10) UNSIGNED NOT NULL DEFAULT 1
AFTER `id_tmnavcmsblockinfo`;

Étape 3 : Peupler les associations existantes

Si des données existent déjà en base, associez-les à votre boutique par défaut :


INSERT INTO `ps_tmnavcmsblockinfo_shop` (`id_tmnavcmsblockinfo`, `id_shop`)
SELECT `id_tmnavcmsblockinfo`, 1
FROM `ps_tmnavcmsblockinfo`
WHERE `id_tmnavcmsblockinfo` NOT IN (
    SELECT `id_tmnavcmsblockinfo` FROM `ps_tmnavcmsblockinfo_shop`
);

Étape 4 : Corriger le modèle ObjectModel

Modifiez la classe PHP du modèle pour déclarer la compatibilité multi-boutique :


class NavCmsBlock extends ObjectModel
{
    public $id_tmnavcmsblockinfo;
    public $id_shop;
    // ... autres propriétés

    public static $definition = array(
        'table' => 'tmnavcmsblockinfo',
        'primary' => 'id_tmnavcmsblockinfo',
        'multilang' => true,
        'multishop' => true,
        'fields' => array(
            'id_shop' => array(
                'type' => self::TYPE_INT,
                'validate' => 'isUnsignedId',
                'shop' => true,
            ),
            // ... autres champs existants
        ),
    );
}

Étape 5 : Corriger la méthode installDB() du module

Pour que le module crée correctement ses tables lors d'une future installation, modifiez la méthode installDB() :


public function installDB()
{
    $return = true;

    // Table principale
    $return &= Db::getInstance()->execute('
        CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'tmnavcmsblockinfo` (
            `id_tmnavcmsblockinfo` INT UNSIGNED NOT NULL AUTO_INCREMENT,
            `id_shop` INT(10) UNSIGNED DEFAULT NULL,
            PRIMARY KEY (`id_tmnavcmsblockinfo`)
        ) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8mb4;
    ');

    // Table multi-boutique
    $return &= Db::getInstance()->execute('
        CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'tmnavcmsblockinfo_shop` (
            `id_tmnavcmsblockinfo` INT UNSIGNED NOT NULL,
            `id_shop` INT(10) UNSIGNED NOT NULL,
            PRIMARY KEY (`id_tmnavcmsblockinfo`, `id_shop`)
        ) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8mb4;
    ');

    // Table traductions
    $return &= Db::getInstance()->execute('
        CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'tmnavcmsblockinfo_lang` (
            `id_tmnavcmsblockinfo` INT UNSIGNED NOT NULL,
            `id_shop` INT(10) UNSIGNED NOT NULL DEFAULT 1,
            `id_lang` INT(10) UNSIGNED NOT NULL,
            `title` VARCHAR(255) DEFAULT NULL,
            `content` TEXT DEFAULT NULL,
            PRIMARY KEY (`id_tmnavcmsblockinfo`, `id_shop`, `id_lang`)
        ) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8mb4;
    ');

    return $return;
}

Le piège du typage : id_shop en string

Un problème subtil mais fréquent : PrestaShop peut retourner id_shop sous forme de string au lieu d'un entier. Si le module effectue une comparaison stricte (===), la validation échoue silencieusement.

Le diagnostic :


$id_shop = (int) Shop::getContextShopID();
// ou
$id_shop = (int) Context::getContext()->shop->id;

Castez toujours id_shop en int avant de l'utiliser dans vos requêtes ou comparaisons.

Vérification rapide avec Shop::getShops()

Pour confirmer que PrestaShop détecte bien vos boutiques, utilisez ce snippet de debug temporaire :


$shops = Shop::getShops();
error_log(print_r($shops, true));

Vous devriez obtenir un tableau associatif contenant au minimum une entrée avec id_shop, name, et active. Si ce tableau est vide, le problème est plus profond : vérifiez la table ps_shop et la configuration multi-boutique dans les paramètres généraux.

Bonnes pratiques pour les développeurs de modules

Checklist multi-boutique

  1. **Table `_shop` obligatoire** pour toute entité ObjectModel
  2. **Propriété `multishop => true`** dans `$definition`
  3. **Colonne `id_shop`** dans la table principale ET la table `_lang` si applicable
  4. **Clé primaire composite** `(id_entite, id_shop)` dans la table `_shop`
  5. **Cast en int** systématique de `id_shop` dans les requêtes
  6. **Hook `actionShopDataDuplication`** pour dupliquer les données lors de la création d'une nouvelle boutique
  7. PrestaShop 8.x : ce qui change

    Depuis PrestaShop 8, le ObjectModel valide plus strictement les associations multi-boutique. Un module qui fonctionnait "par chance" en 1.6 ou 1.7 sans table _shop échouera quasi-systématiquement en 8.x. Si vous migrez, auditez toutes les classes ObjectModel de vos modules tiers avec :

    
    grep -rn "multishop" modules/tm_*/classes/
    

    Tout module sans multishop => true dans ses définitions est un candidat au bug.

#multi-boutique #id_shop #ObjectModel #module #debug #base de données

Questions fréquentes

Tout ce que vous devez savoir sur ce sujet.

Un projet PrestaShop ?

Discutons-en directement.

★★★★★

193 projets livrés

Gratuit & sans engagement — réponse sous 24h

Alexandre Carette

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.