Les deux plugins gèrent tous deux des cours en ligne, des leçons et des quiz, mais leurs types de contenu personnalisés et leurs hooks n’ont presque rien en commun. Pour un développeur qui code une extension complémentaire, capable de fonctionner aussi bien avec Tutor LMS qu’avec LearnDash, ignorer ces différences conduit tout droit à une intégration qui fonctionne avec l’un et échoue silencieusement avec l’autre.
Types de contenu personnalisés : des noms sans rapport
LearnDash construit son architecture autour du type de contenu sfwd-courses pour les cours, sfwd-lessons pour les leçons et sfwd-quiz pour les évaluations, un héritage du nom historique du plugin (Sensei For WordPress… devenu LearnDash). Tutor LMS utilise de son côté courses pour les cours et s’appuie sur les blocs Gutenberg pour structurer les leçons et les quiz à l’intérieur même du contenu du cours, plutôt que de multiplier les types de contenu séparés.
| Aspect | Tutor LMS | LearnDash |
|---|---|---|
| Type de contenu du cours | courses | sfwd-courses |
| Structuration des leçons | Blocs Gutenberg dans le cours | Type de contenu séparé sfwd-lessons |
| Fonction d’accès centralisée | tutor_utils() | Fonctions dédiées par domaine |
| Hook de fin de cours | tutor_course_complete_after | learndash_course_completed |
| Vérification d’inscription | tutor_utils()->is_enrolled() | sfwd_lms_has_access() |
Accès aux données : un objet central contre des fonctions dispersées

Tutor LMS centralise une grande partie de ses accès aux données dans une seule classe utilitaire, instanciée via la fonction tutor_utils(), qui expose des méthodes comme get_courses() ou is_enrolled() :
if ( function_exists( 'tutor_utils' ) && tutor_utils()->is_enrolled( $course_id, $user_id ) ) {
// Logique réservée aux inscrits Tutor LMS.
}
LearnDash, à l’inverse, expose des fonctions procédurales spécialisées par domaine, sans point d’entrée unique équivalent :
if ( function_exists( 'sfwd_lms_has_access' ) && sfwd_lms_has_access( $course_id, $user_id ) ) {
// Logique réservée aux inscrits LearnDash.
}
Pour une extension compagnon des deux plugins, cette différence de philosophie oblige à écrire une couche d’abstraction interne, avec une interface commune, plutôt que d’appeler directement les fonctions de chaque plugin dans le code métier.
Hooks de progression : des moments différents
Le hook tutor_course_complete_after de Tutor LMS se déclenche une fois que l’apprenant a validé l’ensemble des éléments requis du cours, avec l’identifiant du cours et de l’utilisateur en paramètres. LearnDash propose learndash_course_completed, qui transmet un tableau associatif complet contenant le cours, l’utilisateur et un ensemble de métadonnées de progression, plutôt que des identifiants séparés :
// Tutor LMS
add_action( 'tutor_course_complete_after', function( $course_id, $user_id ) {
extension_notifier_fin_de_cours( $user_id, $course_id );
}, 10, 2 );
// LearnDash
add_action( 'learndash_course_completed', function( $data ) {
extension_notifier_fin_de_cours( $data['user']->ID, $data['course']->ID );
} );
La signature du hook LearnDash impose de dépaqueter un tableau, quand celle de Tutor LMS livre directement les identifiants attendus : une extension compagnon doit donc adapter, pour chaque plugin, la façon dont elle extrait les mêmes informations avant d’appeler sa propre logique commune.
Quiz et évaluations
Tutor LMS stocke les résultats de quiz dans des tables personnalisées dédiées, accessibles via ses propres méthodes utilitaires, tandis que LearnDash s’appuie davantage sur des métadonnées utilisateur associées au cours pour retracer la progression. Une extension qui doit exporter des résultats de quiz vers un système externe ne peut donc pas partager la même requête de lecture entre les deux plugins : chacun impose sa propre structure de stockage sous-jacente.
Verdict
Développer une extension réellement compatible avec les deux plugins demande d’accepter, dès la conception, l’absence de terrain d’entente structurel entre eux : les types de contenu, les hooks et les fonctions d’accès aux données divergent presque systématiquement. La stratégie la plus soutenable consiste à isoler, dans une interface interne unique, deux implémentations distinctes, une par plugin, plutôt que de tenter de deviner un comportement commun qui n’existe pas réellement entre Tutor LMS et LearnDash.