Verwandte Artikel in WordPress mit Advanced Custom Fields anzeigen: So geht’s!

Verwandte Artikel in WordPress mit Advanced Custom Fields

Als ich dieses Blog aufsetzte, war ich natürlich auch auf der Suche nach einem Plugin, mit dem ich verwandte Artikel verlinken kann. Es gibt diverse Plugins für WordPress, die das automatisiert machen können, wie z.B. Yet Another Related Posts Plugin oder Contextual Related Posts – ich aber will diese Artikel manuell aussuchen. So habe ich mehr Kontrolle und bin mir sicher, dass die Artikel auch Sinn machen.

Die Anforderungen

Die Anforderungen waren für mich im Detail:

  1. Ich will bei einem Artikel zu anderen Artikeln angeben
  2. Bis zu 3 Verweise sollen unter dem Artikel erscheinen
  3. Verlinke ich einen Artikel, soll dieser Artikel auch automatisch einen Backlink bekommen.
  4. Trotzdem sollen insgesamt nur 3 Artikel in der Liste angezeigt werden, wobei die ausgehenden Links Vorrang haben sollen.

Ich habe mir zunächst das Manual Related Posts Plugin angeschaut, das allerdings seit 7 Monaten nicht mehr aktualisiert wurde. Zudem hatte ich auch ein paar Probleme mit dem Styling, da er z.B. feste style-Angaben in den Code schreibt, die man zwar theoretisch per Filter ändern kann, was aber für mich nicht so richtig funktioniert hat.

Die nächste Idee war dann, das direkt selbst im Theme zu implementieren. Problem hierbei: Benutzer-Interfaces in WordPress zu implementieren ist nicht gerade ein Spaß (zumindest out of the box). Und an dieser Stelle kam dann das Advanced Custom Fields Plugin ins Spiel. Hier muss man zwar immer noch selbst ein bisschen Code schreiben, aber die UI-Arbeit ist damit zum Glück schon erledigt. (Dank geht an Claudia von Chilliscope, die mich wieder dran erinnerte, dass es dieses Plugin ja auch noch gibt).

Was ist das Advanced Custom Fields Plugin (ACF)?

Kurz gesagt, lassen sich mit dem Advanced Custom Fields Plugin neue Metadaten-Felder für Artikel, Seiten und Custom Content Types definieren. Diese Felder sind dabei deutlich ausgereifter im UI als die Standard-WordPress-Implementierung. Hinzu kommt eben, dass man sich um das Benutzer-Interface dann gar nicht mehr selbst kümmern muss.

Allerdings muss man schon etwas programmieren können, um ACF nutzen zu können, denn es fragt nur die Daten ab, zeigt sie aber zunächst nicht wieder an. Dazu muss man das Theme entsprechend anpassen, was PHP-Kenntnisse benötigt.

Verwandte Artikel mit Advanced Custom Fields implementieren

Wie geht man also nun vor, um eine manuelle Verlinkung von Artikeln zu implementieren? Am Anfang steht die Definition des benötigten Feldes, in dem man die Artikel aussucht, die man verlinken will. Dazu legt man unter dem Menüpunkt Eigene Felder zunächst eine neue Gruppe an, die man beliebig nennen kann. Bei mir heißt sie „Post Links“. Direkt darunter kann man dann ein neues Feld erstellen. Als Titel habe ich „Verwandte Artikel“ gewählt, als internen Namen „related_posts“ und als Feld-Typ Beziehung. Man hätte auch den Artikel-Typ nehmen können, aber dann bekommt man nur eine lange Liste von Artikeln angezeigt. Das Beziehungs-Feld dagegen hat noch eine Suche eingebaut ähnlich dem Link-Dialog.

Wichtig für mich war weiterhin, dass ich nur Posts erlaube, dass man nicht zwingend etwas auswählen muss, und dass man mehrere Artikel selektieren kann.

Insgesamt sieht das dann so aus:

Beziehungsfeld für die verwandten Artikel anlegen

Beziehungsfeld für die verwandten Artikel anlegen

 

Bei den Optionen kann man dann noch angeben, dass die Gruppe unter dem Inhalt („normal“) angezeigt werden soll und dass der Stil „Standard“ sein soll (also mit Rahmen). Und bitte nicht vergessen, vorher auch das Feld hinzuzufügen, die Optionen gelten nämlich für die ganze Gruppe.

Optionen in ACF einstellen

Optionen in ACF einstellen

Hat man das alles gemacht, erscheint rechts in der Seitenleiste bei den Artikeln eine neue Box namens „Post Links“, wo man dann beliebig viele Artikel selektieren kann (von denen wir später aber nur maximal 3 anzeigen).

Das Beziehungsfeld in Aktion

Das Beziehungsfeld in Aktion

Optional: Feld-Liste als PHP exportieren

Ich persönlich habe dies zunächst auf meiner Test-Installation gemacht und habe danach unter „Eigene Felder“ den Punkt „Export“ und dann „Export als PHP“ gewählt. Heraus kommt PHP-Code, der in die functions.php im Theme eingebaut werden kann.

Der Vorteil: Ich muss die Feld-Definition nicht bei jedem Blog vornehmen, sondern sie ist fest im Theme verankert (ACF muss aber installiert sein). In meinem Fall kann ich einfach das Theme auf die Live-Site deployen und schon erscheinen die Felder. So würde ich mir das bei allen Plugins wünschen.

Man sollte allerdings die Gruppe im Backend wieder löschen, nachdem man den PHP-Code ins Theme eingebaut hat, da ansonsten die Felder doppelt erscheinen könnten.

Verwandte Artikel ausgeben

Jetzt können wir Artikel selektieren, jedoch werden sie noch nicht ausgegeben. Gehen wir dazu am besten Schritt für Schritt vor. Dazu habe ich in der Datei single.php im HTML einen neuen Bereich für die Artikel-Liste geschaffen und folgenden Code für die Liste selbst genutzt:

<?php
    $related = get_field("related_posts");

    // output all the related articles
    if( $related ): ?>
        <h2>Vielleicht auch total interessant:</h2>
        <div class="row">
        <?php foreach( $related as $post): setup_postdata($post); ?>
        <div class="col-md-4">
            <div class="panel">
                <a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( the_title_attribute( 'echo=0' ) ); ?>" rel="bookmark">
                    <?php echo the_post_thumbnail("featured-wide", array( 'class' => 'img-responsive') ); ?>
                    <div class="panel-heading">
                        <h5 class="entry-title clearfix"> <?php the_title(); ?> </h5>
                    </div>
                </a>
            </div>
        </div>
        <?php endforeach; ?>
        </div>
    <?php
    wp_reset_postdata();
    endif;
?>

Noch erfüllt das allerdings nicht alle Anforderungen, vor allem werden die auf diesen Artikel zeigenden Artikel noch nicht dargestellt. Außerdem werden mehr als 3 Artikel angezeigt, wenn sie vorhanden sind. Darauf kann man natürlich im Backend achten, wenn aber noch die eingehenden Links dazukommen, können es auch deutlich mehr als 3 werden.

Eingehende Links darstellen

Um die eingehenden Artikel-Verlinkungen auch darstellen zu können, muss man die Datenbank befragen. Dies geht mit folgendem Code-Schnipsel:

    $incoming = get_posts(array(
        'post_type' => 'post',
        'meta_query' => array(
            array(
                'key' => 'related_posts', // name of custom field
                'value' => '"' . get_the_ID() . '"', // matches exaclty "123", not just 123. This prevents a match for "1234"
                'compare' => 'LIKE'
            )
        )
    ));

Es wird hier wieder das Feld related_posts genutzt, allerdings wird gefragt, welche Artikel die ID des aktuellen Artikels in diesem Feld beinhalten. Die Liste dieser Artikel wird dann in $incoming abgespeichert.

Als nächstes müssen wir das noch mit den ausgehenden Links zusammenführen und auf 3 Artikel insgesamt begrenzen:

    if (!$related) {
        $related = array();
    }
    $related = array_merge($related, $incoming); // merge own and incoming together

    // limit to 3 articles, own links always take precedence
    $related = array_slice($related, 0, 3);

Wichtig ist auch der erste Teil, wo wir sicherstellen, dass die $related-Variable auch wirklich ein Array ist, damit array_merge keinen Fehler wirft.

Insgesamt kommen wir dann auf folgenden Code:

<?php
    $related = get_field("related_posts");

    // merge in articles pointing to this post
    $incoming = get_posts(array(
        'post_type' => 'post',
        'meta_query' => array(
            array(
                'key' => 'related_posts', // name of custom field
                'value' => '"' . get_the_ID() . '"', // matches exaclty "123", not just 123. This prevents a match for "1234"
                'compare' => 'LIKE'
            )
        )
    ));
    if (!$related) {
        $related = array();
    }
    $related = array_merge($related, $incoming); // merge own and incoming together

    // limit to 3 articles, own links always take precedence
    $related = array_slice($related, 0, 3);


    // output all the related articles
    if( $related ): ?>
        <h2>Vielleicht auch total interessant:</h2>
        <div class="row">
        <?php foreach( $related as $post): setup_postdata($post); ?>
        <div class="col-md-4">
            <div class="panel">
                <a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( the_title_attribute( 'echo=0' ) ); ?>" rel="bookmark">
                    <?php echo the_post_thumbnail("featured-wide", array( 'class' => 'img-responsive') ); ?>
                    <div class="panel-heading">
                        <h5 class="entry-title clearfix"> <?php the_title(); ?> </h5>
                    </div>
                </a>
            </div>
        </div>
        <?php endforeach; ?>
        </div>
    <?php
    wp_reset_postdata();
    endif;
?>

Und das ist auch der Code, der jetzt hier auf der Site im Einsatz ist. Dank Advanced Custom Fields war das recht flott zu implementieren und erfüllt alle meine Anforderungen. Ein ingesamt kleines Beispiel, aber man sieht gut daran, dass hier mit etwas Fantasie noch sehr viel mehr möglich ist.

Was habt ihr denn so damit gebaut?

 

Vielleicht auch total interessant: