Submitted by zempa on
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>
<
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.
Ah ça fait plaisir de voir
Permalien Soumis par Yoran le 7 Juillet, 2010 - 12:47
Ah ça fait plaisir de voir quelqu'un avoir ce genre de précocupations :)
personnellement ce que je fais dans mes blocs c'est :
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 :
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
Permalien Soumis par zempa le 7 Juillet, 2010 - 14:11
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,
Permalien Soumis par zempa le 7 Juillet, 2010 - 17:31
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.
oui mais alors là pour le
Permalien Soumis par Yoran le 7 Juillet, 2010 - 18:26
oui mais alors là pour le coup, ça t'apporte quoi par rapport à un template de block ?
Déjà, vu que je suis en
Permalien Soumis par zempa le 7 Juillet, 2010 - 18:40
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. ^^