[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"theme-db":3,"$fKnz2vuX4bZz1LbUTiuFsvSZ3e07l5_5fqNYp4Tzdhi8":22,"$fYn69xNKXRPdH0hluw3usizPlsg0P8qDWDPXu3GR7KCE":103,"megamenu":140,"$fZfVo-8BbXvu31s1F6xV8i8_GixVIh1FdNF4dBGksPcU":196,"footer-db":210,"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",{"columns":23},[24,40,70,91],{"title":25,"links":26},"Plateforme",[27,31,34,37],{"label":28,"href":29,"external":30},"Offre Starter (2 500 €)","\u002Foffre-starter",false,{"label":32,"href":33,"external":30},"Devenir Ambassadeur","\u002Fambassadeur",{"label":35,"href":36,"external":30},"Modules PrestaShop","\u002Fmodules",{"label":38,"href":39,"external":20},"CodeMyShop.com","https:\u002F\u002Fcodemyshop.com",{"title":41,"links":42},"Le Synedre",[43,46,49,52,55,58,61,64,67],{"label":44,"href":45,"external":30},"L'histoire","\u002Fsynedre",{"label":47,"href":48,"external":30},"Constitution","\u002Fsynedre\u002Fconstitution",{"label":50,"href":51,"external":30},"L'équipe","\u002Fequipe",{"label":53,"href":54,"external":30},"Le réacteur en direct","\u002Freacteur",{"label":56,"href":57,"external":30},"Le Drill (entraînement)","\u002Fdrill",{"label":59,"href":60,"external":30},"Protocole de réunion","\u002Fsynedre\u002Freunion",{"label":62,"href":63,"external":30},"Les agents IA","\u002Fagents-ia",{"label":65,"href":66,"external":30},"La Conduite","\u002Fsynedre\u002Fconduite",{"label":68,"href":69,"external":30},"Charte plateforme","\u002Fsynedre\u002Fcharte",{"title":71,"links":72},"Ressources",[73,76,79,82,85,88],{"label":74,"href":75,"external":30},"Blog","\u002Fblog",{"label":77,"href":78,"external":30},"Academy","\u002Facademy",{"label":80,"href":81,"external":30},"Dictionnaire","\u002Fdictionnaire",{"label":83,"href":84,"external":30},"Expertise PrestaShop","\u002Fexpertise",{"label":86,"href":87,"external":30},"Flywheel","\u002Fflywheel",{"label":89,"href":90,"external":30},"Manifeste","\u002Fmanifeste",{"title":92,"links":93},"À propos",[94,97,100],{"label":95,"href":96,"external":30},"Alexandre Carette","\u002Fa-propos",{"label":98,"href":99,"external":30},"Dossier de presse","\u002Fpresse",{"label":101,"href":102,"external":30},"Contact","\u002Fcontact",{"title":104,"slug":105,"metaDescription":106,"category":107,"tags":108,"difficulty":114,"psVersions":115,"content":118,"faq":119,"tldr":135,"readingTime":136,"generatedAt":137,"publishDate":137,"relatedArticles":138,"sourceCategory":139},"Module PrestaShop sans affichage : corriger un AdminController défaillant","module-prestashop-admincontroller-page-blanche-correction","Votre module PrestaShop affiche une page blanche ? Découvrez les causes courantes : nommage du contrôleur, placement du constructeur et cache à purger.","developpement",[109,110,111,112,113],"AdminController","module PrestaShop","page blanche","debug","back-office","intermediaire",[116,117],"1.7","8.x","\u003Ch2>Le symptôme classique : un module installé mais invisible\u003C\u002Fh2>\n\u003Cp>Vous avez développé votre premier module PrestaShop avec une interface d'administration, l'installation se passe sans erreur, le menu apparaît dans le back-office… mais quand vous cliquez dessus, c'est le néant. Page blanche, aucun champ, aucun listing. Le module semble fantôme.\u003C\u002Fp>\n\u003Cp>Ce problème touche énormément de développeurs PrestaShop, et la cause est presque toujours la même : une incohérence dans le nommage du contrôleur admin ou un constructeur mal positionné.\u003C\u002Fp>\n\u003Ch2>Comprendre la convention de nommage des AdminController\u003C\u002Fh2>\n\u003Cp>PrestaShop impose une convention de nommage stricte pour les contrôleurs d'administration. Le moindre écart provoque un échec silencieux — pas d'erreur, juste une page vide.\u003C\u002Fp>\n\u003Ch3>La règle d'or\u003C\u002Fh3>\n\u003Cp>Trois éléments doivent être parfaitement synchronisés :\u003C\u002Fp>\n\u003Col>\n\u003Cli>**Le nom du fichier** : `AdminGestionRecetteController.php`\u003C\u002Fli>\n\u003Cli>**Le nom de la classe** : `AdminGestionRecetteController`\u003C\u002Fli>\n\u003Cli>**La déclaration dans le module** : référence à `AdminGestionRecette` (sans le suffixe `Controller`)\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cpre>\u003Ccode class=\"language-php\">\n\u002F\u002F fichier : modules\u002Fmonmodule\u002Fcontrollers\u002Fadmin\u002FAdminGestionRecetteController.php\n\nclass AdminGestionRecetteController extends ModuleAdminController\n{\n    \u002F\u002F ...\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Les erreurs fréquentes\u003C\u002Fh3>\n\u003Ctr>\u003Cth>Erreur\u003C\u002Fth>\u003Cth>Exemple\u003C\u002Fth>\u003Cth>Conséquence\u003C\u002Fth>\u003C\u002Ftr>\n\u003Ctr>\u003Cth>Fichier mal nommé\u003C\u002Fth>\u003Cth>`AdminGestionrecetteController.php` (minuscule)\u003C\u002Fth>\u003Cth>Contrôleur introuvable\u003C\u002Fth>\u003C\u002Ftr>\n\u003Ctr>\u003Cth>Classe qui ne correspond pas au fichier\u003C\u002Fth>\u003Cth>Fichier `AdminRecetteController.php` avec classe `AdminGestionRecetteController`\u003C\u002Fth>\u003Cth>Page blanche\u003C\u002Fth>\u003C\u002Ftr>\n\u003Ctr>\u003Cth>Oubli du préfixe `Admin`\u003C\u002Fth>\u003Cth>`GestionRecetteController.php`\u003C\u002Fth>\u003Cth>Non reconnu comme contrôleur admin\u003C\u002Fth>\u003C\u002Ftr>\n\u003Ctr>\u003Cth>Suffixe `Controller` manquant dans le nom de fichier\u003C\u002Fth>\u003Cth>`AdminGestionRecette.php`\u003C\u002Fth>\u003Cth>Autoload échoue\u003C\u002Fth>\u003C\u002Ftr>\n\u003Ch2>Positionner correctement le constructeur\u003C\u002Fh2>\n\u003Cp>Une erreur subtile mais redoutable : placer l'appel à \u003Ccode>parent::__construct()\u003C\u002Fcode> avant la définition de \u003Ccode>$this->fields_list\u003C\u002Fcode>. PrestaShop initialise le helper list dans le constructeur parent. Si vos champs ne sont pas encore définis à ce moment-là, le listing sera vide.\u003C\u002Fp>\n\u003Ch3>La mauvaise approche\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-php\">\nclass AdminGestionRecetteController extends ModuleAdminController\n{\n    public function __construct()\n    {\n        parent::__construct(); \u002F\u002F Trop tôt !\n\n        $this-&gt;table = 'recette';\n        $this-&gt;identifier = 'id_recette';\n        $this-&gt;className = 'Recette';\n        $this-&gt;lang = false;\n        $this-&gt;bootstrap = true;\n\n        $this-&gt;fields_list = [\n            'id_recette' =&gt; ['title' =&gt; 'ID', 'align' =&gt; 'center', 'class' =&gt; 'fixed-width-xs'],\n            'name'       =&gt; ['title' =&gt; 'Nom', 'filter_key' =&gt; 'a!name'],\n            'active'     =&gt; ['title' =&gt; 'Actif', 'active' =&gt; 'status', 'type' =&gt; 'bool', 'align' =&gt; 'center'],\n        ];\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>La bonne approche\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-php\">\nclass AdminGestionRecetteController extends ModuleAdminController\n{\n    public function __construct()\n    {\n        $this-&gt;table = 'recette';\n        $this-&gt;identifier = 'id_recette';\n        $this-&gt;className = 'Recette';\n        $this-&gt;lang = false;\n        $this-&gt;bootstrap = true;\n\n        \u002F\u002F Définir fields_list AVANT l'appel parent\n        $this-&gt;fields_list = [\n            'id_recette' =&gt; ['title' =&gt; 'ID', 'align' =&gt; 'center', 'class' =&gt; 'fixed-width-xs'],\n            'name'       =&gt; ['title' =&gt; 'Nom', 'filter_key' =&gt; 'a!name'],\n            'active'     =&gt; ['title' =&gt; 'Actif', 'active' =&gt; 'status', 'type' =&gt; 'bool', 'align' =&gt; 'center'],\n        ];\n\n        parent::__construct(); \u002F\u002F Maintenant que tout est prêt\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Cette règle s'applique aussi à \u003Ccode>$this->fields_form\u003C\u002Fcode>, \u003Ccode>$this->bulk_actions\u003C\u002Fcode> et toute propriété que le constructeur parent exploite lors de l'initialisation.\u003C\u002Fp>\n\u003Ch2>Purger le cache : l'étape qu'on oublie toujours\u003C\u002Fh2>\n\u003Cp>PrestaShop maintient un index des classes pour accélérer l'autoloading. Quand vous ajoutez ou renommez un contrôleur, cet index est obsolète et votre nouveau fichier est tout simplement ignoré.\u003C\u002Fp>\n\u003Ch3>Sur PrestaShop 1.7 et 8.x\u003C\u002Fh3>\n\u003Cp>La méthode la plus fiable est de supprimer manuellement le fichier d'index :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">\n# Supprimer le cache d'index des classes\nrm -f var\u002Fcache\u002Fdev\u002Fclass_index.php\nrm -f var\u002Fcache\u002Fprod\u002Fclass_index.php\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Vous pouvez aussi vider le cache depuis le back-office via \u003Cstrong>Paramètres avancés > Performances > Vider le cache\u003C\u002Fstrong>, mais en cas de problème de contrôleur, la suppression manuelle du \u003Ccode>class_index.php\u003C\u002Fcode> est plus sûre car elle force une reconstruction complète.\u003C\u002Fp>\n\u003Cblockquote>\u003Cp>\u003Cstrong>Astuce PrestaShop 8.x :\u003C\u002Fstrong> Si vous travaillez en mode debug (\u003Ccode>_PS_MODE_DEV_\u003C\u002Fcode> à \u003Ccode>true\u003C\u002Fcode> dans \u003Ccode>config\u002Fdefines.inc.php\u003C\u002Fcode>), le cache est reconstruit automatiquement à chaque requête. Activez-le systématiquement en développement.\u003C\u002Fp>\u003C\u002Fblockquote>\n\u003Ch2>Déclarer correctement le contrôleur dans le module\u003C\u002Fh2>\n\u003Cp>Le fichier principal du module doit enregistrer l'onglet d'administration. Voici la structure complète :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">\n\u002F\u002F monmodule.php\n\nclass MonModule extends Module\n{\n    public function __construct()\n    {\n        $this-&gt;name = 'monmodule';\n        $this-&gt;tab = 'administration';\n        $this-&gt;version = '1.0.0';\n        $this-&gt;author = 'Alexandre Carette';\n        $this-&gt;need_instance = 0;\n        $this-&gt;bootstrap = true;\n\n        parent::__construct();\n\n        $this-&gt;displayName = $this-&gt;l('Mon Module');\n        $this-&gt;description = $this-&gt;l('Gestion des recettes depuis le back-office.');\n    }\n\n    public function install()\n    {\n        return parent::install() && $this-&gt;installTab();\n    }\n\n    public function uninstall()\n    {\n        return parent::uninstall() && $this-&gt;uninstallTab();\n    }\n\n    private function installTab()\n    {\n        $tab = new Tab();\n        $tab-&gt;active = 1;\n        \u002F\u002F \"AdminGestionRecette\" — sans le suffixe Controller\n        $tab-&gt;class_name = 'AdminGestionRecette';\n        $tab-&gt;name = [];\n\n        foreach (Language::getLanguages(true) as $lang) {\n            $tab-&gt;name[$lang['id_lang']] = 'Gestion Recettes';\n        }\n\n        $tab-&gt;id_parent = (int) Tab::getIdFromClassName('AdminParentModulesSf');\n        $tab-&gt;module = $this-&gt;name;\n\n        return $tab-&gt;add();\n    }\n\n    private function uninstallTab()\n    {\n        $id = (int) Tab::getIdFromClassName('AdminGestionRecette');\n        if ($id) {\n            $tab = new Tab($id);\n            return $tab-&gt;delete();\n        }\n        return true;\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>Utiliser le générateur de modules PrestaShop\u003C\u002Fh2>\n\u003Cp>Pour éviter ces erreurs de structure dès le départ, PrestaShop met à disposition un générateur de squelette de module via le validateur officiel. Cet outil produit une arborescence conforme avec les bons nommages, les bons répertoires et un \u003Ccode>composer.json\u003C\u002Fcode> prêt à l'emploi.\u003C\u002Fp>\n\u003Cp>C'est un gain de temps considérable, surtout pour les premiers modules : plutôt que de deviner la convention, on part d'une base fonctionnelle et on se concentre sur la logique métier.\u003C\u002Fp>\n\u003Ch2>Checklist de diagnostic rapide\u003C\u002Fh2>\n\u003Cp>Si votre contrôleur admin affiche une page blanche, vérifiez dans cet ordre :\u003C\u002Fp>\n\u003Col>\n\u003Cli>**Nommage** : fichier, classe et déclaration Tab sont-ils synchronisés ?\u003C\u002Fli>\n\u003Cli>**Constructeur** : `parent::__construct()` est-il appelé **après** les définitions de propriétés ?\u003C\u002Fli>\n\u003Cli>**Cache** : avez-vous supprimé `var\u002Fcache\u002F*\u002Fclass_index.php` ?\u003C\u002Fli>\n\u003Cli>**Arborescence** : le fichier est-il dans `modules\u002Fmonmodule\u002Fcontrollers\u002Fadmin\u002F` ?\u003C\u002Fli>\n\u003Cli>**Mode debug** : `_PS_MODE_DEV_` est-il activé pour voir les erreurs PHP ?\u003C\u002Fli>\n\u003Cli>**ObjectModel** : si vous utilisez `$this->className`, la classe Model correspondante existe-t-elle et est-elle accessible ?\u003C\u002Fli>\n\u003Cli>**Permissions** : le profil employé a-t-il les droits sur ce contrôleur (onglet Permissions) ?\u003C\u002Fli>\n\u003C\u002Ful>",[120,123,126,129,132],{"q":121,"a":122},"Pourquoi mon AdminController PrestaShop affiche une page blanche ?","Les trois causes principales sont : un nommage incohérent entre le fichier, la classe et la déclaration Tab ; un appel à parent::__construct() placé avant la définition de fields_list ; ou un cache d'index de classes obsolète. Vérifiez ces trois points dans cet ordre pour résoudre le problème dans la majorité des cas.",{"q":124,"a":125},"Dans quel ordre appeler parent::__construct() dans un ModuleAdminController ?","Toujours appeler parent::__construct() après avoir défini toutes les propriétés du contrôleur (table, identifier, className, fields_list, bulk_actions). Le constructeur parent initialise les composants d'affichage en se basant sur ces propriétés. Si elles ne sont pas encore définies, le listing sera vide.",{"q":127,"a":128},"Comment vider le cache des classes PrestaShop après avoir ajouté un contrôleur ?","Supprimez le fichier class_index.php présent dans var\u002Fcache\u002Fdev\u002F et var\u002Fcache\u002Fprod\u002F. Ce fichier contient l'index d'autoloading des classes. Sa suppression force PrestaShop à rescanner tous les fichiers et à détecter votre nouveau contrôleur. En mode développement (_PS_MODE_DEV_ activé), ce cache est reconstruit automatiquement.",{"q":130,"a":131},"Quelle est la convention de nommage des fichiers AdminController dans un module PrestaShop ?","Le fichier doit se nommer exactement comme la classe qu'il contient, avec le suffixe Controller.php. Par exemple, AdminGestionRecetteController.php pour la classe AdminGestionRecetteController. Le fichier doit être placé dans le répertoire controllers\u002Fadmin\u002F du module. Dans la déclaration Tab, on utilise le nom sans le suffixe Controller : AdminGestionRecette.",{"q":133,"a":134},"Comment déclarer un onglet de menu pour un module PrestaShop 8 ?","Créez un objet Tab dans la méthode install() de votre module. Définissez class_name avec le nom du contrôleur sans le suffixe Controller, attribuez un nom multilingue, choisissez un id_parent pour positionner l'onglet dans le menu, et associez-le à votre module via la propriété module. Sur PrestaShop 8, vous pouvez aussi utiliser le tableau $tabs dans la classe du module pour une déclaration déclarative.","Un AdminController PrestaShop qui affiche une page blanche est presque toujours causé par une incohérence de nommage entre le fichier et la classe, un parent::__construct() appelé trop tôt, ou un cache class_index.php obsolète. Corrigez ces trois points et votre module fonctionnera.",5,"2026-03-21T14:07:34.000Z",[],"PrestaShop pour les développeurs",{"items":141},[142,151,157,163,171,179,184,190],{"id":143,"type":144,"label":145,"href":84,"icon":147,"description":147,"badge":147,"groupTitle":147,"style":147,"gridColumns":147,"cssClass":147,"psCategoryId":147,"showPsChildren":30,"position":148,"children":149,"psChildren":150},41,"link",{"fr":146},"Expertise",null,0,[],[],{"id":152,"type":144,"label":153,"href":75,"icon":147,"description":147,"badge":147,"groupTitle":147,"style":147,"gridColumns":147,"cssClass":147,"psCategoryId":147,"showPsChildren":30,"position":154,"children":155,"psChildren":156},42,{"fr":74},1,[],[],{"id":158,"type":144,"label":159,"href":36,"icon":147,"description":147,"badge":147,"groupTitle":147,"style":147,"gridColumns":147,"cssClass":147,"psCategoryId":147,"showPsChildren":30,"position":160,"children":161,"psChildren":162},43,{"fr":35},2,[],[],{"id":164,"type":144,"label":165,"href":167,"icon":147,"description":147,"badge":147,"groupTitle":147,"style":147,"gridColumns":147,"cssClass":147,"psCategoryId":147,"showPsChildren":30,"position":168,"children":169,"psChildren":170},44,{"fr":166},"Outils IA","\u002Foutils-ia",3,[],[],{"id":172,"type":144,"label":173,"href":29,"icon":147,"description":147,"badge":147,"groupTitle":147,"style":175,"gridColumns":147,"cssClass":147,"psCategoryId":147,"showPsChildren":30,"position":176,"children":177,"psChildren":178},45,{"fr":174},"Offre Starter ✨",{"highlight":20},4,[],[],{"id":180,"type":144,"label":181,"href":78,"icon":147,"description":147,"badge":147,"groupTitle":147,"style":147,"gridColumns":147,"cssClass":147,"psCategoryId":147,"showPsChildren":30,"position":136,"children":182,"psChildren":183},46,{"fr":77},[],[],{"id":185,"type":144,"label":186,"href":96,"icon":147,"description":147,"badge":147,"groupTitle":147,"style":147,"gridColumns":147,"cssClass":147,"psCategoryId":147,"showPsChildren":30,"position":187,"children":188,"psChildren":189},47,{"fr":92},6,[],[],{"id":191,"type":144,"label":192,"href":102,"icon":147,"description":147,"badge":147,"groupTitle":147,"style":147,"gridColumns":147,"cssClass":147,"psCategoryId":147,"showPsChildren":30,"position":193,"children":194,"psChildren":195},48,{"fr":101},7,[],[],{"academy":197,"blog":198,"expertise":209},[],[199,203,206],{"title":200,"url":201,"score":154,"type":202},"PrestaShop headless avec Nuxt 3 : pourquoi séparer back et front","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fprestashop-headless-nuxt-separation-front-back","blog",{"title":204,"url":205,"score":154,"type":202},"PrestaShop headless : Nuxt 3, pas Next.js — le choix souverain","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fprestashop-headless-nuxt-nextjs-souverainete",{"title":207,"url":208,"score":154,"type":202},"Sylius rachète PrestaShop : ce que ça change pour vous","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fsylius-rachat-prestashop-headless-souverainete",[],{"footer":211},{"theme":212,"description":147,"hours":147,"logo":213,"contact":216,"social":217,"bottomBar":227},"dark",{"src":214,"href":215,"alt":95},"\u002Flogo-ac.svg","\u002F",{"email":147,"phone":147,"address":147,"cta":147},[218,221,224],{"platform":219,"href":220,"label":219},"linkedin","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Falexandre-carette\u002F",{"platform":222,"href":223,"label":222},"malt","https:\u002F\u002Fwww.malt.fr\u002Fprofile\u002Falexandrecarette",{"platform":225,"href":226,"label":225},"github","https:\u002F\u002Fgithub.com\u002Fprest4cafe",{"copyright":147},{"header":229},{"logo":230,"topBar":233,"contactEmail":236,"features":237,"navBar":147},{"src":214,"alt":231,"text":95,"href":215,"class":232},"Alexandre Carette — Architecte E-commerce Souverain","h-10 w-10",{"message":147,"showLanguages":30,"align":234,"languages":235},"left",[],"contact@alexandrecarette.fr",{"showSearch":30,"showWishlist":30,"showLogin":20,"showContact":30,"showCart":30,"stickyHeader":20,"headerLayout":238},"inline"]