Skip to Content
MoodlePartie 12 — AnnexesPièges courants et FAQ

Chapitre 12.3 — Pièges courants et FAQ

Partie 12 : Annexes — « Ça ne marche pas et je ne comprends pas pourquoi. » 9 fois sur 10, la réponse est ici. Classé par domaine. Version de référence : Moodle 5.2.


Top pièges du dev venant du monde JS/React

🔴 Caches (les 5 premiers à connaître)

1. « Mon changement ne s’applique pas. »Purgez les caches : php admin/cli/purge_caches.php. Moodle cache les chaînes de langue, les templates Mustache, le JS compilé, la liste des plugins, la navigation. Le réflexe n°1.

2. « Ma chaîne de langue affiche [[maclé]]. » → Clé absente du fichier lang/en/, ou cache non purgé. Ajoutez la clé, purgez.

3. « Mon changement SCSS de thème est invisible. » → CSS de thème caché. En dev : $CFG->themedesignermode = true;. En prod : purge_caches. Et vérifiez le cache navigateur. Ne jamais laisser themedesignermode en prod (recompile à chaque page).

4. « Mon changement JS (amd/src/) n’a aucun effet. » → En prod, cachejs=true sert amd/build/ : rebuild avec grunt amd. En dev, mettez $CFG->cachejs = false; pour servir src/ directement. Ne jamais éditer amd/build/ (écrasé).

5. « Ma nouvelle capability / tâche / fonction WS n’existe pas. »db/access.php, db/tasks.php, db/services.php ne sont relus qu’à l’upgrade. Bumpez version.php puis php admin/cli/upgrade.php, purgez.

🔴 Plugins

6. « L’update de mon activité écrit sur la mauvaise ligne. » → À l’_update_instance, l’id est dans $data->instance, pas $data->id. Ajoutez $data->id = $data->instance;.

7. « Mes items disparaissent du formulaire à la réédition. » → Données hors table principale non pré-remplies. Implémentez data_preprocessing() dans mod_form.

8. « Mon activité disparaît après duplication de cours. » → Pas de backup Moodle2 : déclarez FEATURE_BACKUP_MOODLE2 et fournissez backup/moodle2/.

9. « Mon bloc n’apparaît pas sur le tableau de bord. » → Capability :myaddinstance manquante (distincte de :addinstance).

10. « J’ai baissé/réutilisé un numéro de version et tout casse. » → La version ne doit jamais reculer (entier monotone). Incrémentez toujours.

🔴 Sécurité

11. « Un utilisateur accède aux données d’un autre. »IDOR : la capability autorise « gérer des X », pas « ce X-ci est le sien ». Filtrez par userid dans chaque requête. Autorisation ≠ appartenance.

12. « Mon action mutante marche sans jeton. » → Il manque require_sesskey() (ou confirm_sesskey()) sur l’action. Toute mutation exige le jeton CSRF.

13. « Du HTML utilisateur s’affiche brut / faille XSS. » → Sortie non échappée. Utilisez s(), format_string() (texte), format_text() (HTML riche) à la sortie. En Mustache, {{ }} (jamais {{{ }}} pour de la donnée utilisateur).

🔴 Formulaires / DML

14. « Erreur SQL bizarre après un changement de schéma. » → En test PHPUnit/Behat, relancez init.php (la base de test n’a pas vos nouvelles tables). En dev normal, rejouez l’upgrade.

15. « Dépassement mémoire dans une tâche cron. »get_records() charge tout en mémoire. Utilisez get_recordset() (streaming) + close().

16. « Requête N+1, page très lente. » → Une requête par élément dans une boucle. Faites une jointure ou get_records_list(). perfdebug révèle le nombre de requêtes.

🔴 JavaScript / Frontend

17. « Ajax.call renvoie un objet bizarre. » → Il renvoie un tableau de promesses : Ajax.call([...])[0] puis await.

18. « Mon écouteur meurt après un rafraîchissement AJAX. » → Nœud remplacé → écouteur perdu. Délégation d’événements sur un ancêtre stable + closest('[data-…]').

19. « Erreur top-level await dans mon module. » → Interdit en AMD. Mettez l’await dans une fonction async (ex. init).

20. « Ma modale AJAX ne s’ouvre pas en test Behat. » → Ajoutez le tag @javascript au scénario (sinon driver sans JS).

🔴 Web services / Next.js

21. « Mon appel WS renvoie 200 mais rien n’est fait. » → Moodle renvoie HTTP 200 même en erreur ; l’erreur est dans le corps (exception, errorcode). Inspectez le payload, pas le status.

22. « Mon token fuit dans le bundle client. » → Variable NEXT_PUBLIC_* = inlinée côté client. Le token va dans une variable serveur (sans NEXT_PUBLIC_), route handlers / server actions uniquement. Révoquez le token exposé.

23. « CORS bloque mon appel Moodle depuis le navigateur. » → N’appelez pas Moodle depuis le navigateur (token + CORS). Passez par votre backend Next.js (proxy).

24. « Token valide mais appel refusé (permission). » → Capability métier de la fonction manquante sur le compte de service. webservice/rest:use ne suffit pas.

🔴 LTI

25. « Launch LTI : invalid signature. » → Mauvais JWKS orienté (chacun signe avec sa clé privée, l’autre valide avec la clé publique correspondante). NTP/clock skew possible.

26. « L’outil LTI ne se charge pas en iframe. »Cookies tiers (SameSite=None; Secure, ITP, CHIPS). Tester en « New window ».


FAQ franche

Moodle est-il headless ? Non par défaut, mais son API de web services (Partie 9) et LTI (Partie 10) permettent de le piloter et de l’intégrer. Pour une app Next.js : web services (token, REST) côté serveur.

Faut-il Composer pour développer un plugin ? Pas pour le plugin lui-même (Moodle ne l’utilise pas pour les plugins). Composer sert à l’outillage de dev (PHPUnit, moodle-plugin-ci). Un plugin s’installe par git/zip, pas par Composer.

Y a-t-il du hot reload ? Non façon Vite. En dev : $CFG->cachejs=false + $CFG->themedesignermode=true évitent les rebuilds, mais le cycle reste sauvegarde → reload. Pour du JS lourd (React embarqué), npm run watch (esbuild) régénère amd/build/.

Pourquoi PHP ? / Puis-je écrire un plugin en autre chose ? Le core est en PHP ; les plugins serveur sont en PHP (imposé). Le frontend est en JS (AMD/ES6, React possible en îlot, Partie 7). Pas de plugin serveur en Node/Python.

Puis-je modifier le code du core ? Non. « Core hack » = écrasé à chaque upgrade, coupe des correctifs de sécurité. Tout se fait en plugins (Parties 6–8) ou par contribution amont.

Quelle version de Moodle choisir pour un projet ? Dernière stable (5.2) par défaut ; dernière LTS si stabilité prioritaire. Vérifiez la compatibilité des plugins et de l’environnement (PHP 8.3+, BDD récentes). Ch. 1.5.

local, block ou mod ? local_ = fonctionnalité transversale du site. block_ = boîte latérale/dashboard. mod_ = activité de cours (notée, dans une section). Ch. 6.1.

React ou pas React dans Moodle ? La plupart du temps non : Mustache + core/* suffisent. React se justifie pour une UI riche à état client complexe (éditeur, wizard). Ch. 7.4/7.6.

Peut-on vraiment tout personnaliser dans un thème ? Oui (100 % du HTML/CSS/JS) — mais le coût est la maintenance des surcharges à travers les upgrades. Ch. 8.4.

Comment gagner de l’argent avec un plugin GPL ? Support, sur-mesure, hébergement, versions « pro » par abonnement au service — jamais licence propriétaire. Ch. 11.8.


La règle d’or, répétée

Ça ne marche pas ? → 1. Purgez les caches. 2. Avez-vous bumpé version.php (si db/*.php changé) ? 3. Débogage activé (DEBUG_DEVELOPER) — lisez l’erreur réelle. 4. Cherchez en anglais (glossaire ch. 12.1) sur moodledev.io, les forums, le tracker.


Chapitre suivant : 04 — Ressources.