drupal 7 pas MVC

Information importante

En raison d'un grand nombre d'inscriptions de spammers sur notre site, polluant sans relache notre forum, nous suspendons la création de compte via le formulaire de "sign up".

Il est néanmoins toujours possible de devenir adhérent•e en faisant la demande sur cette page, rubrique "Inscription" : https://www.drupal.fr/contact


De plus, le forum est désormais "interdit en écriture". Il n'est plus autorisé d'y écrire un sujet/billet/commentaire.

Pour contacter la communauté, merci de rejoindre le slack "drupalfrance".

Si vous voulez contacter le bureau de l'association, utilisez le formulaire disponible ici, ou envoyez-nous un DM sur twitter.

bonjour,
drupal7 est il MVC ?
Si non, quelle sont les possibilités techniques offertes par drupal7 que vous vous interdisez d'utiliser pour être un minimum conforme au MVC ?
Merci d'avance

Forum : 
Version de Drupal : 
Tags : 

Le MVC n'existe pas réellement dans le web car c'est un paradigme qui implique une architecture persistante alors que le web est stateless.
La séparation logique/données/affichage/autre que l'on rapporche d'une architecture n-tiers est plus appropriée.

Ce petit cours de théorie (fort controversée) étant terminé, Drupal permet bien la séparation de la logique et de l'affichage. Cependant, le "moteur de templates" utilisé étant PHPTemplates, il est possible de faire n'importe quoi. Par exemple, écrire de la logique dans un template est possible car c'est du PHP. Il est préférable d'utiliser un preprocess ou un module quelconque pour gérer cette logique et laisser au template que l'affichage bête et méchant.

Bref, pour être conforme à la logique de séparation de la logique et de l'affichage il faut se limiter à certains appels dans les templates dont, à mon sens, la liste exhaustive contient :

  • print/echo $variable;
  • if (!empty($variable)): / endif;
  • foreach($array as $key => $val): / endforeach;

Pour tout ce qui est logique simple (remaniement de données, manipulation de tableaux complexes, etc.) il vaut mieux profiter des fonctions de (pre)process.
Pour tout ce qui est logique complexe (requêtes SQL, création de fragments HTML via des sous templates, formulaires...) il vaut mieux utiliser un module custom et ses hooks.

Rapport à la remarque précédente, en effet, dans une approche stateless, le MVC est un peu bridé aux entournures, c'est un fait. Maintenant l'aspect "stateless" est une chose très relative. On imagine généralement les états situés sur le serveur mais finalement il est aussi possible d'imaginer qu'un ?page=12 est aussi une forme d'état.

Sinon pour revenir au coeur du sujet, un modèle MVC transposé dans le monde Drupal (et ce bien avant la version 7) reposerait sur le thème pour la partie Vue, et les modules sur les parties Contrôleur et Modèle.

Dans une approche simple (et à mon sens imparfaite) on aura donc :

  • Contrôleur : C'est le coeur de drupal qui joue ce rôle à travers l'implémentation d'un hook_menu. L'item du hook_menu va ainsi définir les paramètres du contrôleur qu'il est possible de spécialiser sur à peu prés tout ses aspects (droits, erreurs, etc.). Lorsque le contrôleur valide l'accès à la ressource, il passe la main à une fonction callback qui joue le rôle de modèle dans notre histoire.

  • Modèle: la callback, généralement définie au sein du module qui implémente le hook_menu va opérer la logique métier (accès aux données, traitements, etc.). Dans les anciennes version de Drupal (6 et moins) cette fonction renvoyait directement du markup HTML ce qui cassait clairement le modèle. Généralement pour palier à cela, on définissait alors une fonction de thème via l'implémentation d'un hook_theme dans le module permettant ainsi à la call back de fournir des données à la fonction de thème qui jouait le rôle de "Vue".

  • Vue: La fonction de thème, généralement un template, est implémentée au sein du thème du site et formate les données du modèle pour fabrique le markup.

Comme je le disais, cette approche a quelque soucis : 1. Elle ne tient pas la main du développeur pour l'aspect modèle/Vue. Ce dernier doit déclarer une fonction de thème pour chaque modèle, et penser à l'appeler à la fin de sa fonction callback. Autant dire que dans 99% des cas, ça le saoule et il écrit directement son markup à la fin ;-)

  1. D'un point de vue performance cette approche est assez terrible car le résultat de la callback n'a aucun cache. On repose ainsi donc totalement sur le cache de page, ce qui est plus ou moins acceptable pour un site visité par des anonymes, mais plus du tout pour un site fortement authentifié. Drupal 7 aurait pu régler cela car officiellement la callback est placée dans un block "system-main-content" et ce block aurait pu bénéficier du cache de block. Ce n'est pas le choix qui a été fait et les concepteurs de D7 on préférer miser sur les renderable array.

    En effet, avec Drupal 7 a été globalisé le concept des renderable arrays. Ce sont des tableaux associatifs PHP, qui reprennent en gros ce qui existait pour les formulaires, en permettant de mixer des données et des fonctions de thèmes pour transformer ces données en markup. Il est aussi possible de spécifier, dans ce tableau digne du monde de Cthulhu, des options de cache, permettant de "régler" le problème de performance cité plus haut. En effet, depuis D7, il est possible à une callback de hook_menu de renvoyer soit du markup comme en D6, soit un renderable array.

    Donc pour résumer, le MVC version D6 était quelque chose comme ceci :

- contrôleur: un hook_menu dans un module custom qui déclare la callback "modèle"

  • modèle: une fonction PHP qui effectue les traitement. À la fin de cette fonction on ajoutait systématique une a/ un stockage en cache b/ un appel theme('ma_vue', $mes_données).

  • vue: Dans le module on implémentait un hook_theme dans lequel était déclaré un thème "ma_vue", et on implémentait la vue du modèle soit dans une fonction, soit dans une template.

    En D7 cette approche est censée devenir quelque chose comme cela :

  • contrôleur: un hook_menu dans un module custom qui déclare la callback "modèle"

  • modèle: une fonction PHP qui effectue les traitement et fournit un "renderable array" avec les bonnes options de cache et les bonnes fonctions de thème.

  • vue: le ou les templates/fonctions de thème présentés dans le renderable array et déclaré dans un hook_theme.

    Maintenant je n'utilise ni l'une ni l'autre des deux approches que je ne trouve pas très efficaces. Personnellement j'opte plutôt pour ceci :

  • contrôleur: un hook_menu dans un module custom qui déclare une callback qui effectue des traitement supplémentaire du domaine "contrôleur" (ex. vérification plus poussée des droits ou des arguments).

  • modèle: Un bloc déclaré via hook_block_info et implémenté via hook_block_view. Dans la fonction du block, la seule contrainte est de vérifier que le contrôleur désiré est actif via menu_get_item par exemple.

  • vue: Un template de block au sein du thème.

    Cette dernière approche présente pour moi de nombreux avantages :

  1. Je peux avoir un modèle/vue connecté à plusieurs contrôleurs. Utile par exemple pour gérer un tableau et des fonctions ajouter/supprimer/modifier.

  2. Je peux avoir plusieurs modèles/vues connectés à un même contrôleur. Utile lorsque le contrôleur conditionne plusieurs vue au sein d'une même page.

  3. Je peux gérer le cache par modèle de manière simple en jouant sur le cache de block via hook_menu_info

  4. Je n'ai aucune fonction de thème à déclarer, je travaille sur theme_block déjà implémenté par drupal. À chaque modèle, je n'ai donc qu'un template block-XXX.tpl.php à rajouter pour créer sa vue.

    Voilà, maintenant à chacun de voir la chose comme il l'entend :)