WordPress Child-Themes verstehen

Die Zeiten ändern sich.

Dieser Beitrag scheint älter als 13 Jahre zu sein – eine lange Zeit im Internet. Der Inhalt ist vielleicht veraltet.

Mit der Version 3.0 von WordPress wurde die viel erwartete Funktion der Child Themes integriert – viel erwartet? Ja, leider nicht in Deutschland. Ich vermute, dass es einfach daran liegt, dass der Markt der kostenpflichtigen Themes hier wesentlich kleiner ist und die meisten Entwickler komplett neue Themes erstellen und nicht auf eine Basis setzen. Aber egal, nun gibt es eine Lösung dafür und ich möchte am Beispiel den neuen Standard-Theme TwentyTen zeigen, wie man es nutzt. Ein weiteres Beispiel findet ihr im übrigen in meinem WP Basis-Theme (SVN); aktuell nicht die html5-Version.

FYI

Das WordPress Basis Theme wird gepflegt und ebenso gibt es ein Child Theme als Starter dazu.

Die Funktion der Child Themes kann im Grunde bei jedem Theme angewandt werden und die neuen Funktionen erleichtern den Zugriff und das Erstellen einen Child Themes. Im Vorfeld gab es auch Möglichkeiten ein Theme zu verändern ohne die eigentlichen Dateien des Themes stark zu verändern. Mit Hilfe der Unterstützung von Child Themes ist dies nun aber komplett unabhängig und so kann man ein Theme nutzen, kann ohne Problem updaten, und trotzdem eigene Ideen realisieren.

In einigen Beiträgen des Netzes wurde die Child Themes schon angesprochen und ich habe bisher nur Artikel gefunden, die die Aktivierung und Änderung des Stylesheets ansprechen. Daher möchte ich dazu nur kurz eingehen, dass ist im Grunde auch recht einfach und dann die verschiedenen Möglichkeiten im Bezug der Template-Dateien aufzeigen.

Vorteile der Idee Child Theme

Mehr oder weniger versucht jeder Administrator einer WordPress Installation etwas Individualismus zu leben. Dabei gehen nicht alle den Weg eines eigens erstellten Themes. Nicht selten wird ein freies oder kommerzielles Theme genutzt und dann an die eigenen Bedürfnisse angepasst. Dabei haben diverse Themes unterschiedliche Optionen, die aber trotzdem nur selten für das Anpassen ausreichen. Will man die einzelnen Darstellungen anpassen, beispielsweise die Sicht einer Kategorie, führt dies schnell zu sehr starken Veränderungen des Themes. Egal wie umfangreich, ein Update eines Themes ist nicht mehr ohne Probleme realisierbar. Hier kommen die Child Themes ins Spiel.

Mit einem Child Theme kann ein Theme angepasst werden oder man kann ein Theme als „Framework“ nutzen und dabei komplett eigene Ideen umsetzen. Egal wie umfangreich, das eigentliche Theme bleibt unangetastet und kann ein Update erfahren.

Nachteile der Verwendung Child Theme

Wie so oft, wo Vorteile sind, sind auch Nachteile. Nicht selten sind die „Framework“ Themes sehr umfangreich und bringen sehr viele Funktionen mit, die man als Laie nicht mehr überschauen kann und das Anpassen kann viel Mühe und Zeit kosten. Hier können auch die Child Themes nicht helfen.
Einen großen Nachteile sehe ich in der Performance, muss WordPress doch einnen Schritt weiter gehen und sich in zwei Bereichen nach den Templates umsehen und entsprechend ziehen.
Im weiteren werden in der Regel die Stylesheets, wenn man auf sie aufbaut, via @-Regel eingebunden, die Nachteile in der Performance hat.

In allen negativen Punkten kommt es auf Können und Wissen des Entwicklers an, also wie man das Theme bzw. Child Theme erstellt. Damit kann man die Punkte entkräften. Wichtig: die neue Funktion ist kein Freibrief, sie sollte genauso überlegt eingesetzt werden. Aber sie sorgt dafür, dass man sein erstandenes Theme nicht anfassen muss und trotzdem sehr überschaubar Anpassungen vornehmen kann.

Child Theme anlegen

Genug der Vorrede, die man sicher erweitern und diskutieren kann. Am Beispiel Theme TwentyTen soll nun eine angepasstes Theme entstehen – ich nenne es TwentyTenJump 😉

Im ersten Schritt wird ein neuer Ordner angelegt, in dem wir alle Template-Dateien, Bilder, Scripte und Stylesheets ablegen – was man im Grunde für das Child Theme benötigt. In diesem Beispiel ist das der Ordner twentytenjump. Um ein Child Theme zu erzeugen und WordPress dieses erkennbar zu machen bedarf es lediglich der style.css innerhalb der neuen Ordners mit diversen Strings in einem Kommentar.

Innerhalb der style.css sieht es wie folgt aus.


@charset "UTF-8";

/**
 * Theme Name:     TwentyTenJump
 * Theme URI:      https://bueltge.de/?p=1192
 * Description:    Child theme for the Twenty Ten theme. Realized for a small tutorial to child themes in WordPress.
 * Author:         Frank Bültge
 * Author URI:     https://bueltge.de/
 * Template:       twentyten
 * Version:        0.1.0
 */

@import url('../twentyten/style.css');

Entscheidend sind die Schlüssel Theme Name und Template. Der Schlüssel Template verweist auf den Ordner-Namen des Theme, welches als Basis gezogen wird – in diesem Beispiel das Theme Twentyten.

Hinweis: Um das Stylesheet des Parent Theme zu referenzieren habe ich im obigen Code-Beispiel die @import Regel genutzt. Dies macht es funcktioniernd und leicht verständlich. Nachteil ist die schlechte Performance diese Möglichkeit und daher ist es in jedem Fall besser die Stylesheets wie auch Scripte etc. über eine Funktion in der functions.php des Child Themes zu laden. Ein Beispiel in Code findet ihr beispielsweise im Basis Child Theme auf Github oder auch im Codex.

Folgenden Aufbau habe ich nun innerhalb der Installation von WordPress.

  • wp-content
    • themes
      • twentyten
      • (das Basis-Theme, inkl. aller Template-Dateien)

        • style.css
        • index.php
      • twentytenjump
        • style.css (muss diese Namenskonvetion erfüllen: style.css)

Damit sind die ersten Voraussetzungen geschaffen und man kann das neue Theme im Backend von WordPress aktivieren.
Achtung: der Verweis auf das Basis-Theme ist nicht sonderlich auffällig, so dass man die Abhängigkeit übersehen könnte. Darum also immer kontrolliert ein Theme löschen. Am verwendeten Theme gibt es keinerlei Hinweis, dass ein anderes Theme als Child-Theme auf dieses Theme zugreift.

Child Themes in WordPress

Am Stylesheet drehen

Ab nun kann man jede beliebe Änderung in dem eigenen Stylesheet ablegen. Ebenfalls kann natürlich der Aufruf des Stylesheets @import url('../twentyten/style.css'); aus dem Basis-Theme entfallen und man kann sich komplett eigene Stylesheet-Strukturen aufbauen.

Man nutzt quasi die Template-Dateien, den Aufbau und das PHP-KnowHow vom Basis Theme, in dem Fall Twenty Ten. Man kümmert sich ausschließlich um das Design und das im beliebigen Umfang. Beispielsweise könnte das im einfachsten Fall eine Farbänderung des Hintergrund sein und alternativ kann ein komplett eigenes Design kreiert werden.

Templates ersetzen

Die Funktionalität des Child Theme lässt aber mehr zu als das Änderung des Aussehen. So kann man bestehende Template-Dateien des Basis-Themes ersetzen. WordPress sucht quasi im ersten Schritt im übergeordneten Child Theme und dann im Basis-Theme nach dem möglichen Template. Durchläuft dabei die Hierarchie der Template-Dateien.

An vielen Punkten vom Theme kann man via Hook eingreifen, was aber nicht jedem Nutzer liegt und kompliziert erscheint. So wird nicht selten die Ausgabe des Titel im head einer Website mit eigenen Funktionen oder von Plugins ersetzt. Man kann entweder via Hook den Titel bearbeiten oder die Ausgabe über eine Funktion steuern. Für das Beispiel soll nun der Titel mit einer Funktion aus einem Plugin ausgegeben werden. In dem Fall muss die header.php bearbeitet werden und darum muss man wie folgt vorgehen, so dass das Basis-Theme unangetastet bleibt.

Es ist lediglich die header.php, die den head-Abschnitt für das Theme enthält in das eigene Child Theme zu kopieren und hier kann sie beliebig bearbeitet werden. Ab nun zieht WordPress diese header.php und nicht mehr die Original-Datei aus dem Basis Theme Twenty Ten.

Damit kann nun auch die angesprochene Funktion in den Title integriert werden, ein Beispiel:


<title><?php
    /*
     * Print the <title> tag based on what is being viewed.
     * We filter the output of wp_title() a bit -- see
     * twentyten_filter_wp_title() in functions.php.
     */
    if ( function_exists('seo_title_tag') )
        seo_title_tag();
    else
        wp_title( '|', true, 'right' );

    ?></title>

Das Basis-Theme bleibt unangetastet, kann weiterhin via Updates auf dem neusten Stand gehalten werden und ab nun zieht WordPress die header.php immer aus dem Child Theme.

Wie in diesem kleinen Beispiel kann man jedes Template ersetzen und so an die eigenen Anforderungen angepasst werden. Trotzdem sollte man bedenken, dass man das Template komplett ersetzt – in dem Beispiel-Fall würde man also ein Update der header.php nicht mitbekommen. Insofern kann es nützlich sein, wenn man auf diverse Bereiche besser via Hook zugreift und diese in eigenen Funktionen abbildet, dazu gleich mehr.

Wichtig: eine Ausnahme ist die functions.php, dazu im Anschluss mehr.

Templates erweitern

Um eigene Anforderungen zu erfüllen, kann es sein, dass man neue Templates benötigt, Template-Dateien die es im Ist-Zustand nicht im Basis-Theme nicht gibt. Im Sinne der Hirarchie kann man immer erweitern. Beispielsweise besitzt Twenty Ten keine home.php – sollte man die aber definieren wollen, also dann wenn die definierte Home-Seite des Backend im Frontend geladen wird, dann kann man diese Datei einfach in das Child-Theme ablegen und WordPress zieht diese Datei, wenn der Zustand is_home() wahr ist.

Mit WordPress Version 3.0 gibt es aber eine weitere Möglichkeit außerhalb der Template-Hirarchie um eigene Templates einzubringen – get_template_part().
Diese Funktion wird konsequent innerhalb von Twenty Ten verwendet – damit muss man in diversen Fällen keine eigenen Templates für den kompletten Aufruf anlegen, sondern lediglich den Abschnitt des Loop.
Beispielsweise nutzt Twenty Ten für die Darstellung der Kategorie-Archive den Aufruf get_template_part( 'loop', 'category' );. Damit ist es möglich, dass in unserem Child Theme ein Template abgelegt wird, was diesen Loop bedient. Es ist also lediglich eine Datei loop-category.php anzulegen und dort alle notwendigen Infos abzulegen.
Im folgenden Beispiel passe ich den Loop an, wenn man sich einem der vier Kategorien befindet. Weitere Änderungen sind möglich, so dass man volle Kontrolle und Flexibilität erhält.


// Anpassungen des Loop
if ( in_category( array(47, 37, 27, 45) ) ) {
    query_posts( 'cat='.$cat.'&posts_per_page=-1&orderby=title&order=ASC' );
}   else {
    query_posts( 'cat='.$cat.'&posts_per_page=20&paged='.$paged );
}
while ( have_posts() ) : the_post(); ?>

Ähnlich könnte man so den Loop für die index.php anpassen – Template Datei loop-index.php wäre dann im Spiel

Funktionen einbringen

Natürlich kann man auch innerhalb des Child-Theme eigene Funktionen einbringen. Wenn man eine eigene functions.php im Child Theme ablegt, dann ersetzt diese Datei nicht die functions.php des Basis-Theme!
Es werden immer die Funktionen des Basis-Theme genutzt; man muss sie via Hook deaktivieren. Die Möglichkeit wird auch in einer Doku in der Datei functions.php erklärt.


add_action( 'after_setup_theme', 'my_child_theme_setup' );
function my_child_theme_setup() {
        // We are providing our own filter for excerpt_length (or using the unfiltered value)
        remove_filter( 'excerpt_length', 'twentyten_excerpt_length' );
        ...
}

Innerhalb der Funktion my_child_theme_setup() kann man nun Funktione des Basis-Theme deaktivieren und eigene Funktionen einbringen.

Weitere Funktionen gehören in die functions.php des Child Themes – das Basis-Theme bleibt immer unangetastet. Im folgenden Code dazu ein Beispiel.
Dabei deaktiviere ich die Funktion des Basis Theme Twenty Ten zur Länge des Excerpt und lade dazu eine eigene Funktion twentytenjump_excerpt_length() und es wird ein Widget eingebracht.


<?php
function twentytenjump_setup() {
    
    remove_filter( 'excerpt_length', 'twentyten_excerpt_length' );
    add_filter( 'excerpt_length', 'twentytenjump_excerpt_length' );
    
    add_action( 'widgets_init', 'register_limited_catagories_widget' );
}
add_action( 'after_setup_theme', 'twentytenjump_setup' );

function twentytenjump_excerpt_length( $length ) {
    return 10;
}

class limited_catagories_list_widget extends WP_Widget {
    
    function limited_catagories_list_widget(){
        $widget_ops = array( 'classname' => __('Selective categories'), 'description' => __('Show a list of Categories, with the ability to exclude categories') );
        
        $control_ops = array( 'id_base' => 'some-cats-widget' );
        $this->WP_Widget( 'some-cats-widget', __('Selective Catagories'), $widget_ops, $control_ops );
    }
 
    function form ( $instance){
        $defaults = array( 'title' => __('Catagories'), 'cats' => '', 'count' => 0 );
        $instance = wp_parse_args( (array) $instance, $defaults );
        $count = isset($instance['count']) ? (bool) $instance['count'] :false;
        ?>
        <p>
            <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
            <input id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" class="widefat" />
        </p>
        <p>
            <input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id('count'); ?>" name="<?php echo $this->get_field_name('count'); ?>"<?php checked( $count ); ?> />
            <label for="<?php echo $this->get_field_id('count'); ?>"><?php _e( 'Show post counts' ); ?></label><br />
        </p>
        <p>
            <label for="<?php echo $this->get_field_id( 'cats' ); ?>"><?php _e( 'Categories to exclude (comma separated list of Category-IDs): ' ); ?></label>
            <input id="<?php echo $this->get_field_id( 'cats' ); ?>" name="<?php echo $this->get_field_name( 'cats' ); ?>" value="<?php echo $instance['cats']; ?>" class="widefat" />
        </p>
        <?php
    }
 
    function update($new_instance, $old_instance) {
            $instance = $old_instance;
            $instance['title'] = strip_tags( $new_instance['title'] );
            $instance['count'] = !empty($new_instance['count']) ? 1 : 0;
            $instance['cats']  = strip_tags( $new_instance['cats'] );
            return $instance;
    }
 
    function widget($args, $instance){
        extract( $args );
        $title = apply_filters('widget_title', $instance['title'] );
        $c     = $instance['count'] ? '1' : '0';
        $cats  = $instance['cats'];
        echo $before_widget;
        if ( $title )
            echo $before_title . $title . $after_title;
        echo '<ul>';
        wp_list_categories("exclude=$cats&title_li=&show_count=$c");
        echo '</ul>';
        echo $after_widget;
    }

}

function register_limited_catagories_widget(){
    register_widget('limited_catagories_list_widget');
}
?>

Fazit

Ich meine aktuell, dass durch die Einführung des neuen Standard-Theme Twenty Ten sicher einige neue schöne Funktionen hinzugekommen sind. Ich denke aber ebenso, dass Twenty Ten sehr ungeeignet ist um die Arbeit von WordPress im Bereich des Themes zu verstehen. Gerade Einsteiger und PHP-Neulinge werden sich schwer tun. Trotzdem entstehen so neue Möglichkeiten und will man Child Themes sauber nutzen, dann kommt man um das Verständnis der Hooks in der WordPress API nicht herum. WordPress führt die Idee der Hooks konsequent fort, schon immer in Plugins beliebt, machen sie sich nun auch in Themes breit. Alles hat Vor- und Nachteile.
Nutzt man aber ein gut gepflegtes Theme oder Framework, dann wird man die neuen Möglichkeiten schätzen und kann so immer ohne Probleme Updaten. Entscheidend wird das eigene Wissen um WordPress sein – je nach Interesse, Wissensstand und Arbeitsweise kann man eigene Themes erstellen. Man sollte sich im Vorfeld Gedanken machen und nicht blind loslegen und wie so oft, am Theme schrauben.

Download:

Zum Abschluss noch das Theme mit den entsprechenden Template-Dateien als Download, so dass man einen kleinen Start zum Spielen hat.

Download als zip-Datei: twentytenjump.zip – 5 kByte
Einen Stand online einsehbar und erweiterbar, eventuell gepflegt findest du auf Github: github.com/bueltge/TwentyTenJump

Info

Das WordPress Basis Theme wird gepflegt und ebenso gibt es ein Child Theme als Starter dazu.

Von Frank Bültge

bueltge.de [by:ltge.de] wird von Frank Bültge geführt, administriert und gestaltet. Alle Inhalte sind persönlich von mir ausgewählt und erstellt, nach bestem Gewissen und Können, was die Möglichkeit von Fehlern nicht ausschließt.