Licht ins Dunkel: Drupal's Render Array

27.07.2013

Drupal 7 gibt Themern eine neue mächtige Möglichkeit in die Hand: Den Render Array. Dieses kleine Tutorial soll den Einstieg im Umgang mit den Render Arrays erleichtern.

Wer sich schon in Drupal 6 mit der Form API auseinandergesetzt hat, der wird sich recht schnell mit den Render Arrays zurecht finden. Für alle anderen sind einige Sachen, wie auch mir zu Beginn, nicht unbedingt klar. Das Problem liegt dabei auch an der teilweise widersprüchlichen Dokumentation.

Für den Einstieg bietet sich der Artikel auf Drupal.org an, jedoch ist der Verweis auf die Form API mit Vorsicht zu genießen, Form API und Render Arrays sehen sich äußerst ähnlich, aber sind eben nicht das Gleiche. So funktioniert der Array-Key `#type bspw. eben auch nur innerhalb eines Form Arrays, wer hier einen einen normalen Render Array bemüht, wird verzweifelt nach dem Fehler suchen, da keine Ausgabe generiert wird.

Was enthält ein Render Array?

Die Antwort: Alles Mögliche.

Drupal übergibt den Template-Files, im Allgemeinen immer einen Render Array. Dieser wird dann der render()-Funktion übergeben um das entsprechende HTML zu erzeugen. Leider muss man sagen, nutzen nicht alle Module die Möglichkeit des Render Arrays, denn der aus Drupal 6 bekannte Weg ist natürlich nach wie vor möglich.

Die Vorteile von Drupal's Render Arrays

Die Vorteile von Render Arrays im Vergleich zu vorgerenderten Variablen liegt darin, dass der Themer bis zur letzten Schicht die Möglichkeit hat, diesen nach seinen eigenen Bedürfnissen anzupassen.

Render Arrays in der Praxis

Soweit in Kürze zur Theorie. Nun die Praxis.

Für den Aufbau eines Render-Arrays in Drupal gilt es folgendes zu beachten: Array-Keys denen eine Raute (#) vorangestellt ist, werden als Properties behandelt, alle "sonstigen" Keys als Kindelemente. Das heißt also, Render-Arrays können auch geschachtelt werden und somit weitere Render-Arrays enthalten.

Beispiel:

<?php
$render_array = array(
   '#property' => 'VALUE',
   'kind' => array(
       '#markup' => 'hier steht text',
   ),
);
?>

Den einfachsten Render Array den man erzeugen kann, z.B. in einer Preprocess-Funktion, könnte folgendermaßen aussehen:

<?php
$variables['render_array'] = array(
    '#markup' => 'Das ist einfach nur Text und oder Markup',
);

$variables['render_array'] = $render_array;
?>;

In der Template-File würde man nun einfach wie folgt vorgehen:

<?php print render($variables['render_array']); ?>;

Und würde entsprechend den Wert aus #markup gerendert bekommen.

An dieser Stelle sei auf ein weiteres Verhalten von Render Arrays hingewiesen: In einer Template-Datei kann derselbe Render Array nur einmal gerendert werden. Was heißt das?

Angenommen die Tpl sehe wie folgt aus:

<?php print render($variables['render_array']); ?>;
<?php print render($variables['render_array']); ?>;

Man würde erwarten, dass nun auch zweimal der Wert aus #markup ausgegeben wird, aber dem ist nicht so. Die render()-Funktion ergänzt das Render-Array beim ersten Durchlauf wie folgt:

array(
   '#markup' => 'Das ist einfach nur Text und oder Markup',
   '#printed' => TRUE,
);

Dadurch soll vermieden werden, dass Werte/Markup versehentlich doppelt generiert und ausgeben wird. Will man dies dennoch, so muss man den Wert von #printed entsprechend auf FALSE setzen.

Folgende Eigenschaften (Properties) stellt Drupal coreseitig zur Verfügung:

  • #type
  • #markup
  • #prefix/#suffix
  • #pre_render
  • #post_render
  • #theme
  • #theme_wrappers
  • #cache

Die genauen Beschreibungen sind auf drupal.org im Dokument Render-Arrays in Drupal 7 zu finden.

hide()/show()

Mit den Funktionen hide() und show() ist es möglich Kindelemente mehrdimensionaler Render-Arrays gezielt ein und auszublenden. So lassen sich bestimmte Elemente zu einem späteren Zeitpunkt rendern.

Ein Beispiel

<?php
// Zum Beispiel in der template.php
$variables['render'] = array(
   'kind1' => array(
         '#markup' => 'Das ist einfach nur Text und oder Markup',
    ),
   'kind2' => array(
        '#markup' => 'Das ist Text von kind2',
    ),
);
?>;


<?php
// In der tpl-File.
hide($render['kind1'];
print render($render); // Kind1 wird nicht ausgeben da hide() angewendet wurde.
print render($render['kind1'];
?>;

#theme

Dem Array Key #theme kann als Wert eine Theme-Funktion zugewiesen werden, welche aufgerufen werden soll, wenn der Array durch render() läuft. Als Wert kommen alle vom Drupal Core sowie von Modulen implementierten Theme-Funktionen in Frage, dabei einfach das Prefix 'theme_' weglassen. Bsp: theme_image würde den Wert image ergeben.

Doch um genau zu wissen, wie man den Render Array aufbauen muss, muss man die gewünschte Theme-Funktion und ihre Übergabe-Parameter kennen.

Beispiel: theme_image($variables):

Wir wollen mittels Render-Array ein Bild ausgeben. Dazu schauen wir uns in der Dokumentation die erwarteten Parameter an. Dabei ist vor allem wichtig, was sich innerhalb $variables versteckt. Nach Dokumentation erwartet die Theme-Funktion (teils optional) Array-Einträge innerhalb von $variables:

  • path
  • width
  • height
  • alt
  • title
  • attributes

Und wie sieht nun der Render Array dazu aus? Allen erwarteten Variablen stellt man die Raute (#) im Render Array voran:

// Beispiel für einen Render Array für theme_image.
$ra = array(
  '#theme' => 'image', // Aufzurufende Theme-Funktion
  '#path' => 'Pfad/Zum/Bild',
  '#alt' => 'Alt-Text',
  '#attributes' => array(
    'id' => 'meine-id',
  ),
);

Übergibt man nun diesen Array in render(), erhält man das gewünschte Markup.

Fazit

Die Render-Arrays sind mächtig und flexibel. Die Lernkurve meines Erachtens gerade für Themer mit weniger Dev-Erfahrung steil.

Aber die Vorteile liegen auf der Hand: Es lässt sich jede nur erdenkliche Datenstruktur erzeugen und rendern, gleichzeitig hält man sich die Möglichkeit offen zu einem späteren Zeitpunkt Änderungen vornehmen zu können, was bei einem Array wesentlich einfacher ist, als fertiges Markup ändern zu müssen. Auch eigene Theme-Funktionen können natürlich implementiert und mit Render-Arrays befüttert werden. In einem weiteren Blogpost werde ich näher auf eigene Theme-Funktionen eingehen.

weitere Blogposts

Composer, Drush & Hosteurope

Composer und drush auf einem HostEurope WebServer installieren.

Whatsapp über den Browser

Whatsapp lässt sich nun auch über den Browser nutzen. Und so funktioniert's auf einem Windows Phone.

MacBook Air Flash Storage Firmware Update: FileVault deaktivieren

Wer über den Mac App Store das aktuelle Flash Storage Firmware Update für sein MacBook Air installieren möchte, wird sich unter Umständen wundern, warum sich das MacBook Air nicht wie erwartet verhält.

Safari Dev Tools die Zweite

Wer seine Website mittels Safari-Entwickler-Tools analysieren will, kann dies auch in Verbindung mit seinem iPad oder iPhone tun. Mit nur wenigen Schritten kann dies am Mac realisiert werden.

iPhone: Vibrationsmuster ändern

Wer dem "monotone" Vibrieren seines iPhones überdrüssig ist, kann auch ein neues Vibrationsmuster wählen, gar sein ganz eigenes erstellen.

Drupal: Pathalias aus hierarchischer Taxonomy erzeugen

Über Pathauto lässt sich in Drupal 7 von Haus aus nur der gewählte Term selbst aus einem Taxonomy-Referenz-Feld über Tokens darstellen, wie auch Parent-Terms darstellbar sind, zeigt dieser kurze Beitrag.

OSX: Memcache in Verbindung mit MAMP einrichten

Memcache ist von Hause aus weder Bestandteil von OSX noch von MAMP. Im Netz finden sich viele Tips und Anleitungen, nicht alle haben auf Anhieb funktioniert, daher an dieser Stelle mein Weg der mich nach Rom führte.

Safari Dev-Tools und iPhone Simulator

Für "normale" Webseiten kaum wegzudenken – Tools wie Firebug oder die Entwickler-Tools der Webkit-Browser. Hier ein kleiner Tipp wie sich die Safari-Entwickler Tools auch im iPhone-Simulator nutzen lassen.

PT.II: Power Mac G5 – Webdesign und Webentwicklung?

Teil 2 der Fragestellung, was mit einem Power Mac G5 heute noch möglich ist. Diesmal steht vor allem die Webentwicklung und das einrichten eines Servers im Vordergrund.

PT.I: Power Mac G5 – Webdesign und Webentwicklung?

In Zeiten von MacBooks mit Retina Display, noch dünneren iMacs, stellt sich die Frage, ob ein 8 Jahre alter Power Mac G5 noch für die gegenwärtigen alltäglichen Arbeiten in Sachen Webdesign und Webentwicklung taugt oder nicht.

jQuery Plugin Squeeze Gallery verfügbar

Mein erstes kleines jQuery Plugin Squeeze Gallery steht zum Download bereit. Es handelt sich dabei um ein Image-Accordion.

Geschafft!

Es ist geschafft! Einige Zeit hat es mich gekostet, um meine kleine Portfolio-Seite online zu bekommen. Nun ist es soweit.