Für Menschen · Seien Sie begeistert und Sie werden begeistern !
Die Loop in den Templates des Theme in WordPress ist das Herz einer jeden Ausgabe. Mit zunehmenden Anforderungen wird die Aufgabe an den Entwickler aufwendiger und das Default-Theme von WordPress hilft nicht weiter als Vorlage.
Nicht selten muss daher mit klassichen PHP-Möglichkeiten im Template die Umsetzung realisiert werden, denn es gibt dafür keine eigene Funktion oder Template Tag, wie einige Nutzer meinen. Da die Frage recht oft auftaucht und man in dem Fall eine Lösung aufzeigen kann, möchte ich mal darstellen, wie ich dafür sorge, dass Inhalte, die in einem Loop ausgegeben wurden, nicht in einem weiteren Loop nochmal dargestellt werden.
WordPress identifiziert Beiträge und Seiten eindeutig via ID, die in der Datenbank angelegt sind und die auch bei der Ausgabe in der Loop eine entscheidende Rolle spielen. Alle Zuordnungen oder Verknüpfungen basieren auf der ID. Daher speichere ich im ersten Loop (Loop Nr.1) die IDs, die ausgeben werden, in einem Array. Diese Variable wurde im Vorfeld als Array bestimmt $do_not_duplicate = array();.
<?php
$do_not_duplicate = array(); // vor den Loops Variable als Array setzen
// 1. Loop
query_posts('ca=1,2,3&showposts=5');
while ( have_posts() ) : the_post();
$do_not_duplicate[] = $post->ID; // IDs im Loop merken
// Post ausgeben ...
the_title();
endwhile;
?>
Nach dem nun durch die obige Loop 5 Artikel ausgegeben wurden, haben wir im Array 5 IDs, mit denen wir nun arbeiten können. Im Übrigen kann man sich das Array mit der PHP-Funktion var_dump() anschauen.
In der kommenden Loop Nr.2 sollen nun 15 Beiträge ausgegeben werden, wobei die schon aus Loop Nr. 1 bekannten IDs nicht nochmal erscheinen sollen. Dies könnte sein, wenn Beiträge mehreren Kategorien zugeordnet sind, da beide Loops unterschiedliche Kategorien ausgeben. Ich prüfe nun mit der Funktion in_array(), ob die aktuelle ID $post->ID im Array $do_not_duplicate vorhanden ist. Nur wenn die ID nicht ( !in_array() ) im Array vorhanden, dann wird im Loop Nr. 2 Inhalt ausgegeben.
<?php
// 2. Loop
query_posts( 'cat=4,5,6&showposts=15' );
while (have_posts()) : the_post();
if ( !in_array( $post->ID, $do_not_duplicate ) ) { // IDs prüfen
// Post ausgeben ...
the_title();
}
endwhile;
?>
Wie so oft, gibt es eine Alternative und dazu stellt WordPress einen Parameter im Query bereit - post__not_in, siehe Codex. Auch diesem Parameter übergebe ich alternativ den Array und in diesem Query sind dann die IDs nicht enthalten. Je nach dem, welchen Weg man geht, stehen damit zwei unterschiedliche Syntax bereit, um doppelten Content zu vermeiden.
<?php
// weiterer Loop ohne Duplikat
query_posts( array(
'cat' => 456,
'post__not_in' => $do_not_duplicate
)
);
while ( have_posts() ) : the_post();
// Post ausgeben ...
the_title();
endwhile;
?>
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.
Das Weblog wird angetrieben von WordPress und aktuell gibt es 980 Beiträge, 18728 Kommentare in 14 Kategorien und 464 Tags.
Das Blog wird liebevoll mit xHTML & CSS in Handarbeit gestaltet. Erstellt mit ♥ zum Befüllen und Erhalten.
Design und Code ist unter Copyright
© 2001 - 2012 bueltge.de [by:ltge.de]
23. September 2009 um 13:31
Schön erklärt und gut umsetzbar. Ich verwende diese Variante bereits seit längerem auf meinem Blog
http://www.der-prinz.com. Interessant wäre nun noch eine Lösung, die in nur EINEM Loop Duplikate vermeidet.Beispiel: Wenn ein Beitrag in Kategorie 1 und in Kategorie 2 abgelegt ist und die jeweils drei aktuellsten Beiträge beider Kategorien im Loop ausgegeben werden, soll der Beitrag aber nur einmal angezeigt werden.
23. September 2009 um 13:49
Guter Artikel. Hab diese Lösung genau so auch schon lange im Einsatz Gerade wenn man WP mehr als CMS einsetzt kommt man ohne diese Lösung fast nicht mehr aus.
23. September 2009 um 16:16
Danke Frank, nachdem ich ihn schon so damit genervt habe
Hab das bei mir nun auch im Einsatz auf der Startseite:
http://www.davidhellmann.comund es klappt wunderbar!!23. September 2009 um 23:13
Sollte man vielleicht erwähnen, in Variante 1 von Loop2 erscheinen eben gerade nicht die gewünschten 15 Postings, wenn es tatsächlich doppelten Content rauszufiltern gibt. Richtig?
Von daher wäre die Variante 2 von Loop2 ja eh vorzuziehen.
Kann man nicht sogar sagen, dass nur Variante 2 das eigentlich WP-Bordmittel nutzt, da Variante 1 einfach nur ein Argument, welches die Funktion
query_posts()mitbringt, nicht nutzt?24. September 2009 um 10:11
Die Variante 2 nutzt einen Parameter, während Loop Nr. 2 der Variante 1 das Filtern via PHP-Bordmitteln tut. Besser ist Variante 2, da es dann auch 15 Beiträge sind, wenn es die IDs im Array gibt. Ansonsten kann es sein, dass nur ein Teil der Artikel kommt, es wird der Loop nicht erweitert.
26. September 2009 um 22:10
Den post_not_in - Parameter kannte ich noch nicht. Sehr praktisch. Ich finde auch, dass damit die zweite Variante noch etwas besser ist.
16. November 2009 um 15:22
Hallo Frank,
danke für den schönen Tipp.
Ich baue mir grade ein Magazin-Theme worin ich diese Funktion super einbauen kann.
Leider klappt dies aber nicht ganz so wie ich das will, deshalb brauche ich deinen Rat.
Ich gebe auf meiner Startseite 5 Kategorien aus.
In den Kategorien befinden sich jeweils 3 Artikel (1Großer, 2 Kleine) und eine Liste.
Insgesammt sollen die letzten 10 News ausgegeben werden (die 3 Artikel und die restlichen 7 sollen als Liste dargestellt werden.).
Soweit so gut.
Ich habe es hin bekommen das er mir die ersten 3 Artikel ausgibt, in der Liste aber zeigt er mir wieder alle Artikel bis auf den Aktuellsten an (also Dublikate).
Eigentlich ist es auch Logisch da er sich ja nur auf die eine ID des ersten Beitrages bezieht.
Da ich aber pro Beitrag einen Loop habe müsste man das ganze in ein extra Array abspeichern, leider habe ich keine Ahnung wie das gehen soll.
Vllt. kannst du mir da weiterhelfen.
Meinen Code würde ich dir gern Parallel per Mail rüberschicken + ein Screenshoot für ein besseres optisches Verständnis.
Danke!
23. November 2009 um 16:21
@Nick: Die ID des Post speichere ich in
$do_not_duplicate[] = $post->ID;, also hat diese Variable alle IDs drin, die nun im Loop ausgegeben werden. Daher muss nun im jeweiligen Loop geprüft werden, ob die ID da schon drin ist, wenn ja, dann keine Ausgabeif ( !in_array( $post->ID, $do_not_duplicate ) ) {. Eventuell lohnt es, vor jedem Loop den Query zu reseten, immer nach der Loop(endwhile):endwhile; wp_reset_query();27. Oktober 2010 um 12:27
Hallo Frank,
danke für diesen ausführlichen Artikel.
Aber besteht auch die Möglichkeit in einem Loop eines Seiten-Templates, Artikel und eine Seite auszugeben?
Bspl.:
get header
maincol - Hier soll eine seite ausgegeben werden
php ??????? ?
artikel - Hier sollen Artikel ausgegeben werden
php if (have_posts()) : while (have_posts()) : the_post();
get sidebar
get footer
Hoffe Du kannst mir den helfenden Tipp geben.
Danke. VG Stefan
27. Oktober 2010 um 17:19
@Stefan: ja sicher, man kann auch da eigene Loops aufbauen. Im Grunde kann man das beliebig oft machen; aber bitte die Performance nicht außer acht lassen. Alternativ arbeite mit dem WP_Query