Eigen template maken voor Drupal 7

Ingediend door Donny op wo, 12/01/2011 - 18:22

Belofte maakt schuld dus zoals ik enkele weken terug beloofd had om enkele van de verschillende template aanpassingen tussen Drupal 6 en 7 aan te halen in een blogpost zal ik er hier een deel van overlopen.

Indien je nog geen ervaring hebt met het maken van Drupal templates is dat geen ramp, ik overloop per bestand even de belangrijkste zaken. Wens je je er verder in te verdiepen volg dan zeker de links onderaan deze blogpost waar je meer info kan bekomen.

Voor het verdere vervolg is het aangeraden dat je beschikt over kennis van HTML/CSS. PHP kennis is niet noodzakelijk maar wel handig.

Eerst gaan we voor je template een map voorzien waar alle bestanden in terug komen. Maak een map aan met de naam die je wilt geven aan je template in sites/all/themes.

Als voorbeeld doorheen deze blogpost zal ik 'Kanji' als custom template beschrijven. Dus maken we een map aan sites/all/themes/kanji.

Het enige bestand dat eigenlijk echt verplicht is voor je custom template is het .info bestand. Dit bevat namelijk gegevens zoals de template naam, versie, voor welke versie van Drupal, regions, welke bestanden zoals stylesheets of scripts moeten worden meegenomen.

Dus in ons voorbeeld maken we het bestand kanji.info aan in onze Kanji map. (sites/all/themes/kanji/kanji.info)

In ons .info bestand gaan we het volgende mee opgeven:

  • CVS ID (Indien je de template op Drupal.org ter beschikking stelt zal dit bestand automatisch van extra info worden voorzien door CVS, Drupal's versie beheersysteem)
  • Template naam
  • Beschrijving
  • Voor welke versie van Drupal deze geschikt is
  • Welke de template engine
  • Welke stylesheets moeten geladen worden
  • Indien je extra regions wilt buiten de standaard, geven we deze hier ook mee op. Let wel van zodra we één region toevoegen, dienen we ze allemaal op te geven, ook de standaard

Onze .info komt er dus als volgt uit te zien

; $Id$

name = Kanji

description = Hier kan je de beschrijving plaatsen voor je template.

core = 7.x

engine = phptemplate

stylesheets[all][] = style.css

regions[highlighted] = highlighted

regions[sidebar_first] = sidebar first

regions[sidebar_second] = sidebar second

regions[content] = content

regions[help] = help

regions[header] = header

regions[footer] = footer

Wanneer je de map met het .info bestand nu naar je Drupal installatie verplaatst en je gaat in je website naar de template pagina kijken, zal je zien dat deze er ondertussen reeds bij verschijnt.

Alle volgende bestanden zijn echter niet verplicht, wanneer je deze niet toevoegt aan je map, zal Drupal deze automatisch invullen vanuit zijn eigen core bestanden. Je kan deze default bestanden terug vinden in de modules map onder 'system'. Hier zal je bv page.tpl.php, block.tpl.php en anderen terug zien. Je kan deze ook gerust naar je eigen map kopiëren en deze hier verder aanpassen naar je eigen wensen. Bovenaan in die bestanden krijg je ook telkens een overzicht van welke (PHP) variabelen er allemaal beschikbaar zijn binnen dat bestand.

Moest het voorvallen dat je niet tevreden bent over de output op sommige van je pagina's, kan je altijd gaan kijken of er geen extra template bestand voor beschikbaar is. Bv indien je de structuur van reacties wenst te wijzigen kan je in de modules map gaan kijken naar de template bestanden (.tpl) in de map 'comment'. Zoals je zal zien krijg je hier weer extra bestanden, die je weer naar je map kan overnemen en daar naar wens aanpassen.

Aangeraden is het ook nog om een screenshot van je ontwerp te nemen en dit bij in je map te plaatsen, zodat je op de template overzichtspagina een beeld krijgt van hoe de door jouw ontworpen template er uit ziet, dit is echter niet verplicht. (Noem dit bestand screenshot.png

Indien gewenst kan je ook een favicon in je template plaatsen, welke dan de standaard zal zijn wanneer je jouw theme inschakelt. Noem deze favicon.ico om automatisch gevonden te worden.

Bij de vorige versies van Drupal zouden we starten met onze html code die de structuur voor je website bevat te plaatsen in het bestand page.tpl.php, echter sinds Drupal 7 is er een nieuw template bestand toegevoegd dat een deel van deze code overneemt, namelijk html.tpl.php

Zoals je kan zien in onderstaande code zit er nu ook RDF geïntegreert in Drupal. Ook heb ik er een voorbeeld voor een conditionele stylesheet voor IE7 aan toegevoegd. Aan de body tag zullen ook verschillende handige klasses worden toegevoegd.

Maak ook het bestand html.tpl.php aan in je map en neem onderstaande code over en pas aan waar nodig.

    <?php // $Id$   ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
      "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php print $language->language; ?>" version="XHTML+RDFa 1.0" dir="<?php print $language->dir; ?>"
      <?php print $rdf_namespaces; ?>>
   
    <head profile="<?php print $grddl_profile; ?>">
      <?php print $head; ?>
      <title><?php print $head_title; ?></title>
      <?php print $styles; ?>
      <?php print $scripts; ?>
      <!--[if IE]>
        <link type="text/css" rel="stylesheet" media="all" href="<?php print base_path() . path_to_theme(); ?>/ie_styles.css" />
      <![endif]-->
    </head>
    <body class="<?php print $classes; ?>" <?php print $attributes; ?>>
      <?php print $page_top; ?>
      <?php print $page; ?>
      <?php print $page_bottom; ?>
    </body>
    </html>
 

Voor we verder gaan met het aanmaken van bestanden is het misschien beter om de structuur even grafisch voor te stellen, bekijk onderstaande voorstelling even.

Drupal theme structuur

Zoals je kan zien wordt alles bepaald in je .info bestand en bevat page.tpl.php de volledige structuur. Deze wordt ingevuld door blokken (block.tpl.php), een node of nodes (node.tpl.php)

Het volgende bestand dat we gaan aanmaken is page.tpl.php, hier in zullen we het grootste deel van de structuur van onze template opmaken.

In tegenstelling tot in vorige Drupal versies dienen we regio's die we willen uitprinten nu binnen de render() functie op te nemen. De regio's zijn nu ook terug te vinden onder de page variabele.

Waar we voordien de regio header zouden uitprinten met <?php print $header; ?> dienen we dit nu als volgt te doen: <?php print render($page['header']); ?>

Enkele veranderingen binnen dit bestand:

  • Sommige variabelen zijn verdwenen zoals bv de footer_message
  • Het zoekvak kan je niet meer tonen via page.tpl maar dient aan een regio te worden toegekent
  • Primary en secondary links hebben nieuwe benamingen

 
    <div id="page-wrapper">
      <div id="page">

        <div id="header"><div class="section clearfix">
   
          <?php if ($logo): ?>
            <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home" id="logo">
              <img src="<?php print $logo; ?>" alt="<?php print t('Home'); ?>" />
            </a>
          <?php endif; ?>
   
          <?php if ($site_name || $site_slogan): ?>
            <div id="name-and-slogan">
              <?php if ($site_name): ?>
                <?php if ($title): ?>
                  <div id="site-name"><strong>
                    <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home"><span><?php print $site_name; ?></span></a>
                  </strong></div>
                <?php else: ?>
                  <h1 id="site-name">
                    <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home"><span><?php print $site_name; ?></span></a>
                  </h1>
                <?php endif; ?>
              <?php endif; ?>
   
              <?php if ($site_slogan): ?>
                <div id="site-slogan"><?php print $site_slogan; ?></div>
              <?php endif; ?>
            </div> <!-- /#name-and-slogan -->
          <?php endif; ?>
   
          <?php print render($page['header']); ?>
   
        </div></div> <!-- /.section, /#header -->
   
        <?php if ($main_menu || $secondary_menu): ?>
          <div id="navigation"><div class="section">
            <?php print theme('links__system_main_menu', array('links' => $main_menu, 'attributes' => array('id' => 'main-menu', 'class' => array('links', 'inline', 'clearfix')), 'heading' => t('Main menu'))); ?>
            <?php print theme('links__system_secondary_menu', array('links' => $secondary_menu, 'attributes' => array('id' => 'secondary-menu', 'class' => array('links', 'inline', 'clearfix')), 'heading' => t('Secondary menu'))); ?>
          </div></div> <!-- /.section, /#navigation -->
        <?php endif; ?>
   
        <?php if ($breadcrumb): ?>
          <div id="breadcrumb"><?php print $breadcrumb; ?></div>
        <?php endif; ?>
   
        <?php print $messages; ?>
   
        <div id="main-wrapper"><div id="main" class="clearfix">
   
          <div id="content" class="column"><div class="section">
            <?php if ($page['highlighted']): ?><div id="highlighted"><?php print render($page['highlighted']); ?></div><?php endif; ?>
            <a id="main-content"></a>
            <?php print render($title_prefix); ?>
            <?php if ($title): ?><h1 class="title" id="page-title"><?php print $title; ?></h1><?php endif; ?>
            <?php print render($title_suffix); ?>
            <?php if ($tabs): ?><div class="tabs"><?php print render($tabs); ?></div><?php endif; ?>
            <?php print render($page['help']); ?>
            <?php if ($action_links): ?><ul class="action-links"><?php print render($action_links); ?></ul><?php endif; ?>
            <?php print render($page['content']); ?>
            <?php print $feed_icons; ?>
          </div></div> <!-- /.section, /#content -->
   
          <?php if ($page['sidebar_first']): ?>
            <div id="sidebar-first" class="column sidebar"><div class="section">
              <?php print render($page['sidebar_first']); ?>
            </div></div> <!-- /.section, /#sidebar-first -->
          <?php endif; ?>
   
          <?php if ($page['sidebar_second']): ?>
            <div id="sidebar-second" class="column sidebar"><div class="section">
              <?php print render($page['sidebar_second']); ?>
            </div></div> <!-- /.section, /#sidebar-second -->
          <?php endif; ?>
   
        </div></div> <!-- /#main, /#main-wrapper -->
   
        <div id="footer"><div class="section">
          <?php print render($page['footer']); ?>
        </div></div> <!-- /.section, /#footer -->
   
      </div>
    </div> <!-- /#page, /#page-wrapper -->
 

Wanneer je nu je theme zou inschakelen kan je al dadelijk een deel van je aanpassingen zien verschijnen, aangezien we nog geen stylesheets hebben toegevoegd is er natuurlijk nog geen opmaak maar dat voegen we later toe.

Het volgende bestand dat we gaan toevoegen is node.tpl.php, dit bestand bepaald de volgorde van velden (inhoud) en welke klasses of tags ze gaan meekrijgen.

Ook hier heb ik even als voorbeeld node.tpl.php uit Drupal's core genomen. Neem de code over en pas aan waar nodig.

    <div id="node-<?php print $node->nid; ?>" class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>>
   
      <?php print $user_picture; ?>
   
      <?php print render($title_prefix); ?>
      <?php if (!$page): ?>
        <h2<?php print $title_attributes; ?>><a href="<?php print $node_url; ?>"><?php print $title; ?></a></h2>
      <?php endif; ?>
      <?php print render($title_suffix); ?>
   
      <?php if ($display_submitted): ?>
        <div class="submitted">
          <?php print $submitted; ?>
        </div>
      <?php endif; ?>
   
      <div class="content"<?php print $content_attributes; ?>>
        <?php
         
// We hide the comments and links now so that we can render them later.
         
hide($content['comments']);
         
hide($content['links']);
          print
render($content);
       
?>

      </div>
   
      <?php print render($content['links']); ?>
   
      <?php print render($content['comments']); ?>
   
    </div> 
 

Indien je reeds Drupal templates ontwikkeld hebt voor eerdere versies zal je zien dat er ook hier enkele veranderingen hebben plaats gevonden. Enkele variabelen kregen een andere naam en $content (de eigenlijk inhoud of berichttekst) worden nu ook in de render functie geplaatst.

In bovenstaand voorbeeld worden ook de reacties en links even uit de content variabele verborgen om deze later apart terug toe te voegen, zodat je indien nodig hier ook weer aparte klasses aan kan toevoegen.

Andere templatefiles die je nog zou kunnen toevoegen (en overnemen van Drupal's core) zijn:

  • block.tpl.php: Om de opmaak van je blokken te regelen
  • comment.tpl.php: Om het uiterlijk van een reactie aan te passen
  • maintenance-page.tpl.php: Om de onderhoudspagina te stylen
  • overlay.tpl.php: Met de komst van Drupal 7 kan je standaard je pagina's bewerken of door het CMS bladeren van uit een overlay. Deze komt bovenaan je pagina te liggen zodat je de pagina waar je zat eigenlijk niet verlaat. Indien gewenst kan je ook hier aanpassingen aanbrengen.
  • region.tpl.php: Bepaal de gezamelijke opmaak van regions of regio's.
  • En naturlijk nog tal van andere, kijk ook geregeld modules na die je toevoegd, sommige bevatten ook een extra template bestand dat je dan weer kan toevoegen aan je map, zodat je dat bestand ook kan stylen naar je eigen wensen.

Net zoals bij de vorige versies van Drupal is het mogelijk om meer specifieke template bestanden te schrijven zoals bv een page.tpl.php enkel en alleen voor story's of verhalen, dit wordt dan page-story.tpl.php. Of een specifiek bestand voor de regio footer zou dan het volgende zijn: region--footer.tpl.php.

Het grootste deel van de bestanden hebben we nu overlopen, er rest er nog eentje die wel enorm handig is wil je echt je template volledig op maat krijgen. Namelijk template.php

Volgens de Drupal richtlijnen is het aangeraden om geen of zo weinig mogelijk extra custom PHP code in bestanden zoals page.tpl.php of node.tpl.php te plaatsen, hiervoor is er het bestand template.php. Binnen dit bestand kan je al je PHP code kwijt, overschrijf Drupal functies en customize volledig je template.

Als voorbeeld geef ik hier mee hoe je het Main menu (vroegere primary links) van een dropdown functie kan voorzien zodat ook alle submenu's worden opgehaald.

Hernoem kanji in de functie naar de naam van jouw template om het werkende te krijgen. Let ook dat template.php niet wordt afgesloten met een php tag (?>), Drupal zal dit verzorgen, dit bestand toch zelf afsluiten kan voor problemen zorgen.

  <?php
  function kanji_preprocess_page(&$variables) {
    if (isset($variables['main_menu'])) {
      $pid = variable_get('menu_main_links_source', 'main-menu');
      $tree = menu_tree($pid);
      $variables['primary_nav'] = str_replace('menu', 'sf-menu menu', drupal_render($tree));
    } else {
      $variables['primary_nav'] = FALSE;
    }
  } 
 

Nu hebben we bijna al onze template bestanden, maar als je gaat kijken naar je template zie je eigenlijk nog niets van opmaak, dat komt omdat we style.css nog niet hebben toegevoegd waarin we onze look & feel zullen vorm geven. Maak daarom ook het bestand style.css aan, als voorbeeld heb ik enkele regels CSS toegevoegd om onze template toch een beetje vorm te geven. Natuurlijk is de rest aan jezelf om de volledige opmaak te bepalen.

    body {
      background-color: #eee;
      color: #333;
      font-family:"Courier New", Courier, monospace;
      font-size: 12px;
    }
    #page-wrapper {
      margin: 0 auto;
      width: 960px;
    }
    #main-wrapper {
      margin: 20px 0;
    }
    .sidebar {
      margin-left: 10px;
      width: 180px;
    }
    .column {
      border: 5px solid #333;
      float: left;
      padding: 10px;
    }
    #content {
      width: 480px;
    } 
 

Nu hebben we toch al een beetje opmaak binnen onze website. Neem zeker een kijkje op de volgende websites indien je meer info wilt bekomen over het themen voor Drupal:

Als laatste had ik graag nog eens even meegegeven om NOOIT aan Drupal's core bestanden te komen of aan module bestanden, indien je deze wilt themen, neem ze dan over naar je eigen template. Anders krijg je vroeger of laat gegarandeerd problemen bij het updaten van je website!