Mes nouvelles activités ne me laissent que peu de temps pour mettre à jour ce blog. En attendant une éventuelle reprise de mes divagations éditoriales, vous pouvez toujours parcourir les anciens articles. A+ et bonne lecture!

Thèmes Drupal : un style différent pour chaque section de votre site

Sujet:

Rubrique:

Niveau : intermédiaire à avancé

Imaginons un site fictif structuré en trois sections:

  • produit (www.monsite.fr/produit/*),
  • services (www.monsite.fr/services/*),
  • blog (www.monsite.fr/blog/*),

La mise en page de chaque section est identique mais afin de renforcer leur identité propre, chaque section comportera un header d'une couleur différente.

Comment faire cela ?

Comme souvent il existe plusieurs solutions. Dans cet article, nous allons utiliser une solution retenue par l'excellent Basic, un starter thème dont je vous ai vanté les mérites dans un précédent article.

Nous allons ajouter à la balise de chaque page du site une classe CSS qui sera générée en fonction de l'url du site. Ainsi, par exemple, lorsque nous serons sur la page d'un produit, nous aurons:

Ensuite, dans la feuille de style, il suffira de cibler le header avec une règle différente pour chaque section:


/* Le header s'affiche en gris par défaut */

header{

background-color: #ccc;

}

/* Le header s'affiche en rouge dans la section produit */
.section-produit #header {
background: #F00;
}

/* Le header s'affiche en vert dans la section services */
.section-services #header {
background: #0F0;
}

/* Le header s'affiche en bleu dans la section blog */
.section-blog #header {
background: #00F;
}

Comment générer la classe ?

C'est ici que cela se complique, enfin juste un petit peu.

Drupal 6 dispose en standard d'un variable appelée body_classes. Cette variable est utilisée pour stocker toutes les classes dynamiques de la page.

C'est ainsi que l'on y trouve les classes suivantes : front ou not-front, logged-in ou not-logged-in, etc... Très utiles, je vous invite à découvrir toutes ces variables.

On retrouve cette variable dans page.tpl.php :

">

Ces variables sont calculées et définies par Drupal juste avant le traitement de page.tpl.php, le template qui permettra de générer le code html de la page. Ce travail c'est l'œuvre d'une fonction importante appelée template_preprocess_page.

OK, on sait maintenant où sont calculées les valeurs stockées dans body_classes[]. Maintenant comment va-t-on y ajouter nos propres classes ? Tout simplement en créant une fonction de thème "phptemplate_preprocess_page()" qui va être insérée dans le fichier template.php de votre thème. Cette fonction vous permet de rajouter toutes les variables que vous souhaitez rendre disponibles à Drupal lors du traitement de page.tpl.php. A l'inverse de "template_preprocess_page" elle est placée dans votre répertoire de thème et est donc librement éditable.

Allez donc faire un tour dans template.php (créez le si nécessaire), vérifiez que la fonction n'existe pas et insérez les deux fonctions suivantes :


function phptemplate_preprocess_page(&$vars, $hook) {
global $theme;
// Classes for body element. Allows advanced theming based on context
// (home page, node of certain type, etc.)
$body_classes = array($vars['body_classes']);
if (user_access('administer blocks')) {
$body_classes[] = 'admin';
}
if (!$vars['is_front']) {
// Add unique classes for each page and website section
$path = drupal_get_path_alias($_GET['q']);
list($section, ) = explode('/', $path, 2);
$body_classes[] = phptemplate_id_safe('page-'. $path);
$body_classes[] = phptemplate_id_safe('section-'. $section);

if (arg(0) == 'node') {
if (arg(1) == 'add') {
if ($section == 'node') {
array_pop($body_classes); // Remove 'section-node'
}
$body_classes[] = 'section-node-add'; // Add 'section-node-add'
}
elseif (is_numeric(arg(1)) && (arg(2) == 'edit' || arg(2) == 'delete')) {
if ($section == 'node') {
array_pop($body_classes); // Remove 'section-node'
}
$body_classes[] = 'section-node-'. arg(2); // Add 'section-node-edit' or 'section-node-delete'
}
}

}
$vars['body_classes'] = implode(' ', $body_classes); // Concatenate with spaces
}

function phptemplate_id_safe($string) {
// Replace with dashes anything that isn't A-Z, numbers, dashes, or underscores.
$string = strtolower(preg_replace('/[^a-zA-Z0-9_-]+/', '-', $string));
// If the first character is not a-z, add 'n' in front.
if (!ctype_lower($string{0})) { // Don't use ctype_alpha since its locale aware.
$string = 'id'. $string;
}
return $string;
}

Je vous laisse investiguer et comprendre le détail car cette fonction fait un peu plus que nécessaire pour cette exercice. En bref, la fonction récupère l'url utilisée (l'alias pas l'url interne c'est ça qui est fort) pour la transformer en une chaine de caractère. C'est cette chaine qui est utilisée pour nommer la classe en "section-nom_de_la_section". Puis elle est stockée dans $body_classes[].

Et voila, lors de l'affichage d'une page, Drupal 6 va lancer la fonction et créer toutes les classes correspondantes pour les injecter dans la balise.

Exemple:
Si nous sommes dans la section blog, la chaine "section-blog" sera générée par phptemplate_preprocess_page() , stockée dans body_classes[], puis injectée dans page.tpl.php pour que Drupal puisse envoyer au navigateur le code HTML de la page. A ce moment vos CSS prendront le relai et feront afficher le header en bleu.
Vous passez dans la section Services ? Et hop, le header s'affiche en vert.

Victoire ! Non seulement vous savez modifier vos pages en fonction de leur alias mais en plus vous en savez un peu plus sur le système de thème de Drupal...

Qu'en pensez vous ? L'article est-il suffisamment clair ou faut-il préciser certains points ?

Commentaires

  1. Une précision, cet article

    Une précision, cet article est à but pédagogique, il permet de se plonger dans le système de thème de Drupal...

    Pour les flemmards, deux solutions :
    * Utiliser un thème comme "basic "qui a cette fonction en standard,
    * Utiliser un module comme "section", http://drupal.org/project/sections, qui permet de spécifier un style, voir un thème différent pour chaque section

    Bref, plein de solutions pour tous les gouts !

  2. Merci Alexandre pour cet

    Merci Alexandre pour cet article, Drupal n'est pas fait pour les flemmards du moins si l'on veut obtenir un résultat satisfaisant. sinon j'ai remarqué qu'il y a très peu de communauté françaises qui traitent de drupal (pour le maroc ca faut même pas rêver).

  3. Drupal pour les flemmards

    Merci pour ton commentaire.

    D'après moi, Drupal est utilisable à plusieurs niveaux, dont un accessible sans écrire une ligne de code, voir mon article sur Ineaguide. Après bien sur, mais cela est vrai pour n'importe quel outil, il faut de la patience et de la persévérance pour en sortir une belle réalisation.

    Quand à certaines communautés francophones hors de France, le problème tient à la taille critique des utilisateurs dans chaque pays. Ceci dit, si tu penses pouvoir organiser qlq chose, la toute nouvelle association Drupal France et Francophonie devrait pouvoir te donner un coup de main. Mais là on dérive du sujet de cet article.

  4. Juste pour compléter, il y a

    Juste pour compléter, il y a aussi l'approche de la sélection automatique de template. Sur une URL de type "www.monsite.fr/produit/12/afficher" pour reprendre ton exemple, phpEngine est plutôt bien fichu et va chercher dans l'ordre les templates :
    1. page-produit-12-afficher.tpl.php
    2. page-produit-afficher.tpl.php
    3. page-produit.tpl.php
    4. page.tpl.php

    C'est le même principe que pour le node type, pour un ndoe de type "story", il cherchera :
    1. node-story.tpl.php
    2. node.tpl.php

    Ca ne remplace pas ta technique qui est la seule efficace dés qu'il s'agit d'injecter des variables dans un template mais l'approche nommage est pas mal non plus et très facile à mettre en oeuvre par nos amis graphistes.

    Sinon la liste exhaustive est ici :
    http://drupal.org/node/190815

  5. Effectivement, le cycle de

    Effectivement, le cycle de suggestion pour page.tpl.php est très complet, mais à ma connaissance cela ne marche que pour l'url interne de Drupal, pas pour les alias définis par exemple avec pathauto. Ainsi dans l'exemple que tu cites "produit" ne peut pas être un alias...

    "The suggestions are numerous. The one that takes precedence is for the front page. The rest are based on the internal path of the current page. Do not confuse the internal path to path aliases which are not accounted for. Keep in mind that the commonly used Path auto module works its magic through path aliases."

    Qu'en penses tu ?

  6. Intéressant, j'avoue que je

    Intéressant, j'avoue que je ne m'étais jamais posé la question car j'utilise peu ou pas le module alias dans ce cas de figure. Soit je passe par la taxo et la chaîne de tpl fonctionne avec, soit je fabrique un petit module custom qui ne contient un hook_menu dont le seul rôle est de virer la catégorie (ex. produites/node/12 => /node/12) et de router vers le call back classique du node.

    Je suis justement en train de voir cela avec le site de mediapart qui a les deux cas de figure. Des sections taxonomesques (internat, france, etc.), et des "sous-site" (club, journal, etc.)

  7. hello

    Une solution d'une logique très drupalienne donc intéressante pour cela.
    En revanche à bien considérer cette solution, elle est assez effrayante : ça fait quand même un gros pavé de code php assez obscur pour pouvoir générer une classe css en php en fonction d'une rubrique.

    Je serai curieux de voir une autre solution pour résoudre ce besoin :-)

  8. Je ne voulais pas effrayer

    Je ne voulais pas effrayer ;-). Mais je te remercie pour ton commentaire. Je crois que je vais changer mon exemple qui est trop simpliste et donc la solution un "overkill" par rapport au problème.

    Mais effectivement cela permet de mieux comprendre le système de thème de Drupal.

    Juste quelques précisions :

    • Cela génère un classe CSS en fonction d'un alias d'url, pas une rubrique en tant que telle. Le code consiste simplement à récupérer l'alias et le nettoie pour générer une chaine utilisable.
    • Ce moyen est à utiliser lorsque tous les autres moyens ne sont pas efficaces. Comme le dit Ulhume ci dessus, le système de suggestion répond à de nombreux besoins, on peut ainsi avoir des templates de page différents en fonction : des types de contenus, de l'url interne et surtout de la taxonomie. La taxonomie est un moyen de créer des rubriques et donc la Drupal propose en std un moyen de créer un template par terme de taxonomie.
    • En revanche cette solution est effectivement efficace dans le cas de micro-sites, avec organic group par exemple.

    Pour finir: le système de thème de Drupal n'est pas si compliqué. Une fois que l'on a compris le concept (cela n'est pas l'objet de cet article) on s'aperçoit que tout est possible.

    Pour ceux que cela intéresse, j'en profite pour faire un peu de pub, je suis entrain de préparer une formation de 2 jours dont le but est de permettre de (vraiment) comprendre ce concept, de (bien) comprendre les mécanismes sous-jacent au système de thème afin d'avoir toutes les clés pour réaliser des thèmes qui sortent de l'ordinaire.

  9. Salut, oui désolé pour mon

    Salut, oui désolé pour mon raccourci du mot "rubrique". Encore une fois la solution proposée est intéressante car on est en plein dans la logique du framework de drupal.

    Pour le systeme de theme, il est vrai qu'une fois qu'on a compris la logique sous-jacente tout s'éclaire; le framework de drupal est un langage vraiment particulier qui demande juste un temps pour se familiariser. Surtout quand comme moi on a une aversion naturel pour les arrays ^^

  10. Ya pas de problème, tes

    Ya pas de problème, tes commentaires et ceux des autres ont une véritable valeur. Ils apportent un éclairage différent aux aspects traités dans cet article.

    Bref je ne suis que trop heureux de te voir réagir. Et moi aussi j'aime pas les arrays ;-)

  11. un petit problème...

    Bonjour,
    Un grand merci pour nous faire partager ces astuces, n'étant pas très calé côté PHP, j'ai toujours eu du mal a modifier a ma guise un thème drupal.
    Seulement après avoir suivit à la lettre le tutoriel du dessus, je ne suis pas parvenu a avoir le changement de class du body fonctionnel.
    le body prend la classe:
    à la place de l'alias de la rubrique.
    J'ai du créer le template.php car il n'existait pas.
    ouvert des balises PHP et placé les deux fonctions donnés plus haut.
    Je ne vois pas où est mon erreur, pourriez vous m'aider?
    Merci.

  12. La fonction marche

    La fonction marche correctement puisque vous avez la classe "page-image" qui apparait. Quelle est l'url en question de la page ?

    Avez-vous essayé en créant un noeud test et en lui donnant l'alias suivant masection/letitredunoeud (avec Pathauto).

    Normalement vous devez alors avoir : page-masection-letitredunoeud et section-masection .

  13. Bon, vu que tu avais l'air de

    Bon, vu que tu avais l'air de douter de mon approche, j'ai fait un petit test "standalone":

    Dans le hook_menu d'un module je rajoute :

    $items['rubrique'] = array (
    'type' => MENU_CALLBACK,
    'page callback' => 'tutoriel_menus_rubrique_router',
    'page arguments' => array (),
    'access arguments' => array (
    'access content'
    ),
    );

    Puis la callback :
    function tutoriel_menus_rubrique_router() {
    $args=func_get_args();
    $path=implode("/",$args);
    $return = menu_execute_active_handler($path);
    return $return;
    }

    Du coup /rubrique/xxxx est routé en interne vers /xxxx. Mais comme le theme page n'est appliqué qu'au retour de la callback, phpEngine va lui travailler avec le chemin d'orgine. Du coup, il suffit d'ajouter au thème un page-rubrique.tpl.php, faire un coup de rebuild du cache de thème, et c'est gagné.

    Il est aussi possible de faire des choses plus génériques encore en utilisant un tableau de rubriques, une boucle de création d'items qui passent le nom de la rubrique en premier paramètre.

    Voilà, en espérant que cela serve

  14. Excellent ! Merci de partager

    Excellent ! Merci de partager ton astuce.
    Bravo, et non je ne me serai pas permis de douter de toi ;-)

  15. Oups, alors mon problème

    Oups, alors mon problème viendrait de l'url...
    En fait je n'ai fait les tests que sur des url simple, de type:
    monsite.com/front, monsite.com/photos.
    Cette astuce ne marcherait elle que sur des url a plusieurs niveaux de type: monsite.com/masection/letitredunoeud ?
    c'est un site simple, les url ne contiennent qu'un seul niveau.
    Merci pour la réponse.

  16. Ok ok j'arrête de me la jouer

    Ok ok j'arrête de me la jouer paranoïaque ;-) Content que cela puisse t'intéresser en tout cas.

    Petite précision, il est aussi possible de faire soit-même, dans la callback appel à la fonction theme('page',...) ce qui peut avoir comme avantage d'injecter des variables en place avec notamment le nom de la rubrique (via arg(0)), et donc de faire un peu la même chose que toi en jouant sur la classe.

    bref, une fois de plus, Drupal est une vraie pâte à modeler. Faudrait tenter de faire la même chose avec Joomla pour rire ;-)

  17. Pour ceux qui ne veulent pas coder...

    Et qui veulent changer juste quelques couleurs/styles d'une section à l'autre, il existe Css Injector.

  18. formation

    Ou et quand ta formation de 2 jours ?

    Noémie

  19. Merci

    Merci pour ton post, il m'aide vraiment.

  20. LE module section fonctionne

    LE module section fonctionne très bien,je le recommande !

  21. Attention, les balises code

    Attention, les balises code ont un gros problème dans ce tuto, c'est tout chamboulé !

  22. Balise code

    En effet, dans le magnifique tuto d'Alexandre, en tout début de tuto, pas mal de balises code ont été employée sans que le contenu ne soit rendu fidèlement. :( Cela n'est pas totalement indispensable à sa compréhension mais pourrait y contribuer aisément je pense.

    PS: Salut à tous, et merci à tout un chacun pour le travail que vous faites pour nous permettre d'évoluer dans cet univers.

  23. Salut à tous, Merci encore

    Salut à tous,
    Merci encore pour ce superbe tuto, cela dis j'ignore sur laquelle des balise ces modification sont appliquée. Logiquement je me dis que c'est sur le header vue que c'est lui qui change de couleur suivant les sections sur lesquelles nous pouvons nous trouver. Merci de bien vouloir revoir l'affichage des contenus des balises "code" je vous prie Merci beaucoup, ça pourrais beaucoup nous servir.

  24. ou est quand cette formation

    ou est quand cette formation de 2 jours stp.

 

Guided search

Abonnez-vous au flux RSS de Inéation

Twitter

Commentaires récents