Module : séparer la vue de mon module

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 à tous,

je viens dernièrement de me mettre à Drupal.

J'ai donc été amené à développer mon premier module : il s'agit d'un slideshow de projets avec titre + texte (riche) + visuel. Il s'agit d'un module spécifique au site de test sur lequel je me fais la main; module qui n'apparait que sur la homepage
Pour cela, je me suis basé sur le tutoriel dédié au développement de module.
J'ai donc été amené à créer, dans une premier temps, un type de contenu "projetbt" via CCK ainsi qu'à éditer le template page-front.tpl.php.
Par la suite, afin de garantir l'affichage de ce module, j'ai créé également un template de block pour ce module block-projetbt.tpl.php.
Dans ce module, la récupération des données liées aux nodes "projetbt" se fait via node_load($nid) où $nid est le résultat de la requête "SELECT nid FROM {node} WHERE type = '%s' " (avec %s = "projetbt").

Si tout fonctionne parfaitement, il y a un truc qui me chiffonne.
En effet, le code html de mon slideshow (à savoir une liste

<

ul>

  • contenant plusieurs

    <

    div>) est intégré dans le code du module, code qui est renvoyé via $block['content'].
    Résultat, dans block-projetbt.tpl.php, je me retrouve avec un simple

    <?php
     
    print $block->content;
    ?>

    .

    Or je voulais savoir s'il était possible de séparer la vue du module.
    Par exemple, j'ai tenté de ne renvoyer dans $block['content'] un tableau de contenu ce qui m'a permis de placer tout le html dans block-projetbt.tpl.php : il suffit alors d'une boucle for pour afficher le contenu.
    Non seulement c'est tiré par les cheveux mais en plus ce n'est franchement compatible avec les bonnes pratiques de développement de module.

    Aussi, existe-t-il une méthode pour séparer la vue où dont-on intégrer inévitablement le html de sortie dans le code du module?

    Merci d'avance.

  • Forum : 
    Version de Drupal : 

    Ah ça fait plaisir de voir quelqu'un avoir ce genre de précocupations :)

    personnellement ce que je fais dans mes blocs c'est :

    <?php
    return array(
      
    'subject'=>'foo',
      
    'champ1'=> valeur1,
      
    etc..
      
    'champn'=> valeurn);
    ?>

    Ensuite je crée un template nommé block-nom_du_module-delta_du_block.tpl.php
    dans lequel je peux accéder à mes champs comme ceci :

    <?php
     
    foreach ($block->champ1 as $item) ...
    ?>

    Le coup du 'content'=>'foo' tient à ce que Drupal ne colle le bloc dans le région qui si 'content' est renseigné... preuve que l'on doit être rare à faire ce genre d'exercice...

    Merci Yoran pour ta réponse et pour le coup du ‘content’=>’foo’ que je ne savais pas.
    Cela ressemble un peu à ce que j'avais tenté (avec succès) mais en plus propre.

    Entre temps, j'ai regardé du coté des hooks de thème qui peuvent aller dans le même sens.
    Je reviendrai plus tard si cela a été fructueux ou non.

    Merci encore.

    Choses promise chose due, j'ai pu séparer proprement la vue via les hooks theme.

    Je vais être certainement très long mais ça pourra servir à quelqu'un d'autre et ça me permettra de remettre les choses à plat! ^^
    A noter que je me suis inspiré du module comment.

    Comme évoqué précédemment, mon module affiche une liste ul-li contenant plusieurs div et évidement le contenu.
    J'ai donc un theme pour le wrapper correspondant à la balise ul (ouvrante et fermante) et un theme pour le li.

    Dans un premier temps, je déclare les deux themes comme suit:

    <?php
    function projetbt_theme() {
      return array(
       
    'projetbt' => array(
         
    'template' => 'projetbt',
         
    'arguments' => array('node'=>NULL),
        ),
       
    'projetbt_wrapper' => array(
         
    'template' => 'projetbt-wrapper',
         
    'arguments' => array('content' => NULL),
        ),
      );
    }
    ?>

    Je définis donc les deux fichiers templates pour chacun des themes (plus les variables attendues)

    Le wrapper projetbt-wrapper.tpl.php contient donc

    <?php
    // $Id:$
    ?>

    <div class="slideshowContent">
       <ul id="listProjets">
          <?php print $content; ?>
    </ul>
    </div>

    Pour le template projetbt.tpl.php :

    <?php
    // $Id:$
    ?>

    <li>
       <div class="projet">
           <?php if($visual){ ?>
                <div class="visuel" style="overflow:hidden">
                 <?php print $visual; ?>
              </div>
           <?php } ?>
           <div class="content">
              <p class="title"><?php print $title; ?></p>
                <div class="text"><?php print $text; ?></div>
              <?php print $link; ?>
            </div>
       </div>
    </li>

    Pour le wrapper, il n'y a rien d'autre à faire mais pour projetbt.tpl.php, je vais passer par template_preprocess_projetbt() pour définir les variables $title, $visual, $text et $link :

    <?php
    function template_preprocess_projetbt(&$vars){
     
    //Params
     
    $node = $vars['node']; //node étant la variable attendu de ce hook_theme.
     
    $img = $node->field_img;
     
    $options['attributes'] = array("class"=>"more");
     
    $options['html']=true;
     
    //Vars
     
    $vars['title']     = check_plain($node->title);
     
    $vars['visual'] = '<img alt="'.check_plain($node->title).'" src="'.base_path().$img[0]["filepath"].'" />';
     
    $vars['text']   = check_markup($node->body,2,false);
     
    $vars['link']   = l('<span class="right"><span class="left">'.t("En savoir +").'</span></span>','node/'.$node->nid, $options);
    }
    ?>

    Maintenant que tout cela est défini, il faut remplir les cases (variables des templates) de contenu via la fonction theme().

    Donc il faut dans un premier temps récupérer chacun des noeuds voulus et cela au moyen de la fonction projetbt_get_nodes_content() créée pour l'occasion.

    <?php
    function projetbt_get_nodes_content(){
     
    //Params
     
    $content = '';
     
    $nType = "betatilt_projet";
     
    $limitnum = variable_get("projetbt_nbshow", 5);
     
    //Query
     
    $req = "SELECT n.nid FROM {node} n WHERE type = '%s' ";
     
    $rs = db_query_range(db_rewrite_sql($req), $nType, 0, $limitnum);
     
    //Traitements
     
    while($obj = db_fetch_object($rs)){
       
    $nid = $obj->nid;
       
    $node = node_load($nid);
       
    $content.= theme('projetbt',$node); // Ici on récupère le contenu HTML du template
     
    }
      return
    $content;
    }
    ?>

    Maintenant on revient sur le hook_block() pour afficher l'ensemble pour la partie $op=="view" :

    <?php
    function projetbt_block($op, $delta=0, $edit = array()){
      [...] 
    //ici le code pour list
     
    else if($op=="view"){
        
    $content = projetbt_get_nodes_content(); //On récupère le contenu de chaque node
        
    $block = array();
        
    $block['subject'] = 'Projet BT';
        
    $block['content'] = theme('projetbt_wrapper',$content); //On récupère le contenu du wrapper auquel on a injecté le contenu de chaque node c'est à dire de chaque li
        
    return $block;
      }
    }
    ?>

    Voili voilou.

    PS : j'ai du créer un block-projetbt.tpl.php dans mon theme pour n'afficher que le content uniquement.

    Déjà, vu que je suis en apprentissage de Drupal, ça me permet de comprendre un peu plus les choses. ^^

    Mais surtout, cela respecte le dev de module (la variable $content renvoie le contenu par exemple et cela fait moins bidouille) et cela me permet de me passer du template de block : le module se suffit alors à lui-même.
    Ainsi à terme si je veux produire un module utilisable pour n'importe theme sans trop de manip (hors skin css) c'est à dire ici sans repasser par un template de block, il me semble qu'il est préférable de procéder ainsi.

    Mais, c'est vrai que ça donne l'impression de cueillir un fleur avec une moissonneuse batteuse... m'enfin c'est Drupal qui veut ça. ^^