Unser Affiliate Theme ist da! Spare 10% mit dem Gutschein DRWP10 - mehr erfahren!
Achtung! Dieser Artikel wurde nach dem Relaunch von wpsnippets.de noch nicht überarbeitet und kann fehlerhaft in der Formatierungen sein.

Mit WordPress virtuelle Unterseiten erzeugen

In diesem Beitrag möchte ich euch erklären, wie Ihr für bestehende Seiten, Beiträge oder auch Custom Post Types virtuelle Unterseiten erstellen könnt.

Diesem Problem müssen mussten wir uns gerade erst bei einem Kundenprojekt stellen, wo es um mehrere Unterseiten zu jedem erstellten Beitrag geht. Aufgrund der Indexierung durch Suchmaschinen waren Content-Tabs mit jQuery oder CSS3 von vorne rein direkt ausgeschlossen. Da der Kunde natürlich nicht pro Artikel jedes mal bis zu 10 Unterseiten erstellen soll, musste eine Lösung her.
&

Virtuelle Unterseiten? Hä?

Eine virtuelle Unterseite ist eine „fake“-Weiterleitung auf ein bestimmtes Template oder einen bestehenden Inhalt. Dies lässt sich am besten anhand eines Beispiels erklären:

Gegeben ist der Post Type Autos, in diesem Post Type wurde der Artikel Audi veröffentlicht. Der Artikel Audi lässt sich wie folgt im Blog aufrufen:

http://meineSeite.de/auto/audi/

Anhand von benutzerdefinierten Feldern wurden diesem Auto mehrere technsiche Daten (Hubraum, PS, Gewicht, …) hinzugefügt und diese möchten wir gerne auf einer Unterseite ausgeben lassen, ohne diese händisch anzulegen. Der Aufruf sollt folgendermaßen aussehen:

http://meineSeite.de/auto/audi/details/

Dieses Szenario lässt sich wunderbar mit virtuellen Unterseiten lösen. Die Handhabung im Template ist sehr einfach, so hat man die Möglichkeit das Template der single.php ordentlich zu übernehmen, um dem Besucher weiterhin das Gefühl zu geben, er habe den Beitrag Audi nicht verlassen.

Warum keine jQuery Tabs verwenden?

Meiner Meinung nach ist es nicht der richtige Weg um viel Inhalt per jQuery Tabs zu gliedern, hierfür ist es besser Unterseiten anzuelegen. Um nicht für jeden Artikel die entsprechenden Unterseiten manuell anlegen zu müssen, empfehle ich dynamische virtuelle Unterseiten. Das hat auch einen entscheidenen Vorteil für Google, jede Unterseite wird seperat von Google erfasst und nicht wie mit Tabs als eine einzige Seite. Bisher habe ich keine funktionierenden Plugins gefunden, die dieses Feature sauber umsetzen. Andere Content Management Systeme wie Drupal können damit besser umgehen als WordPress.

Das Snippet

Genug geschwafelt. Jetzt erkläre ich euch, wie ihr dieses Snippet sauber in euer Theme einbindet, deswegen seid ihr ja auch hier. :-)

Vorraussetzungen

Euer Post Type muss bestimmte Ressourcen erfüllen. Ihr müsst folgendes Einstellen:

'public' => true,
'publicly_queryable' => true,
'query_var' => true,
'rewrite' => true,
'hierarchical' => true,

Implementieren des Snippets

Kopiert einfach den untenstehenden Code in eure functions.php.

// virtuelle Unterseiten
$virtual_sub_pages = array(
'details' => 'Details',
'news' => 'News'
);

add_filter('rewrite_rules_array', 'vsp_insertrules');
add_filter('query_vars', 'vsp_insertqv');

// Rewrite Rules
function vsp_insertrules($rules) {
global $virtual_sub_pages;
$newrules = array();
foreach ($virtual_sub_pages as $slug => $title) {
$newrules['autos/([^/]+)/' . $slug . '/?$'] = 'index.php?autos=$matches[1]&fpage=' . $slug;
return $newrules + $rules;
}
}

function vsp_insertqv($vars) {
array_push($vars, 'fpage');
return $vars;
}

// WordPress' standard Canonical Funktion entfernen
remove_filter('wp_head', 'rel_canonical');
add_filter('wp_head', 'vsp_rel_canonical');
function vsp_rel_canonical() {
global $current_vp, $wp_the_query;

if (!is_singular())
return;

if (!$id = $wp_the_query->get_queried_object_id())
return;

$link = trailingslashit(get_permalink($id));

// Permalinks der virtuellen Seiten als canonical deklarieren
if (!empty($current_vp))
$link .= user_trailingslashit($current_vp);

echo ' <link href="'.$link.'" rel="canonical" />';
}

Die wichtigen Zeilen im Detail

Zeile 2-6: Hier müsst ihr die gewünschen virtuellen Unterseiten anlegen.

// virtuelle Unterseiten
$virtual_sub_pages = array(
'details' => 'Details',
'news' => 'News'
);

Für das oben beschriebene Szenario, mit dem Post Type Auto, habe ich Details (http://meineSeite.de/auto/audi/details/) und News (http://meineSeite.de/auto/audi/news/) erzeugt.

Zeile 16: An dieser Stelle müsst Ihr die Rewrite Rules an euren Post Type anpassen.

$newrules['autos/([^/]+)/' . $slug . '/?$'] = 'index.php?autos=$matches[1]&fpage=' . $slug;

Ersetzt einfach „autos“ mit eurerem Slug.

Ausgabe im Template

Die virtuellen Unterseiten sind angelegt, nun kommen wir zur verarbeitung im Template. Um eine Ausgabe für die virtuellen Unterseiten zu erzeugen müsst ihr folgende Template Files erstellen:

  • single-autos.php (zur Ausgabe von http://meineSeite.de/auto/audi/)
  • single-autos-details.php (zur Ausgabe von http://meineSeite.de/auto/audi/details/)
  • single-autos-news.php (zur Ausgabe von http://meineSeite.de/auto/audi/news/)

Die Dateinamen müssen natürlich an euer Szenario angepasst werden. Der Aufbau ist wie folgt:

single-POSTTYPE-FAKEPAGE.php

Der Aufbau der single-autos.php muss dann ungefähr so aussehen: (varriert natürlich nach Theme, das Prinzip bleibt aber gleich!):

get_header();

if (!$current_vp) { // Normale Ausgabe von http://meineSeite.de/auto/audi/)

<h1 class="site_title"></h1>
<?php the_content(); ?>

} else if ($current_vp == 'details') { // Ausgabe von http://meineSeite.de/auto/audi/details/)

get_template_part( 'single', 'autos-details' );

} else if ($current_vp == 'news') { // Ausgabe von http://meineSeite.de/auto/audi/news/)

get_template_part( 'single', 'autos-news' );

}

get_footer();

Zusatz für Yoast SEO

Sofern jemand von euch WordPress SEO by Yoast einsetzt, muss die Canoncial Links für diesen Post Type deaktivieren. Hier für gibt es ein kleines Snippet, welches auch in die functions.php eingefügt werden muss:

function wpseo_canonical_exclude( $canonical ) {
global $post;

if (is_singular('autos')) {
$canonical = false;
}

return $canonical;
}

add_filter( 'wpseo_canonical', 'wpseo_canonical_exclude' );

Fertig. Zugegeben, für unerfahrene Anwender ist dieses Snippet nicht unbedingt geeignet, trotzdem ist es der sinnvollste Weg um ohne Plugin dynamische Unterseiten erstellen zu können. Bei Fragen einfach diesen Beitrag kommentieren.

Ich hoffe ich konnte euch weiterhelfen. :-)

Über Christian

Die Webentwicklung ist seit 2006 ein großer Teil meines Lebens und seit 2010 kann ich damit auch meine Brötchen verdienen. Ich beschäftige mich speziell mit WordPress und entwickle auch eigene Themes. Die Anpassungsfähigkeit von Wordpress begeistert mich immer wieder, daher möchte ich euch interessante Snippets und Plugins nicht vorenthalten.

WordPress Affiliate ThemeAnzeige

19 Kommentare

Avatar von Marcel

Marcel 14. Februar 2013 um 12:48

Da wird der Kunde bestimmt Freude haben, super Sache!

Antworten
Avatar von André Köbel

André Köbel 14. Februar 2013 um 12:57

Haha. ;)

Antworten
Avatar von Agnes

Agnes 15. Februar 2013 um 9:05

Wow, das ist ein klasse Ansatz, danke fürs teilen … da kann man wirklich viel mit anfangen.

Antworten
Avatar von Michael

Michael 14. März 2013 um 8:54

Ein super Lösungsansatz, habe ebenfalls eine lange Zeit nach einer eleganten Möglichkeit gesucht und werde diese hier direkt mal ausprobieren.

Besten Dank & liebe Grüße

Michael

Antworten
Avatar von Christian Lang

Christian Lang 14. März 2013 um 11:30

Hallo Michael,

freut mich, dass ich dir mit diesem Artikel weiterhelfen konnte. Wenn du Fragen hast, schreibe mir einfach.

Gruß,
Christian

Antworten
Avatar von Daniel

Daniel 29. Juni 2013 um 15:18

Das ganze klingt ziemlich interessant, ich hätte auch gerade einen Anwendungsfall, nur will es bei mir (WP 3.5.2) keine Unterseiten anzeigen, ich sehe nur die üblichen Seiten in den Custom Post Types. Im WP_DEBUG bekomme ich keine Fehlermeldungen.

Nachdem ich die Codezeilen in die functions.php kopiert und den CPT angepasst habe, sollten doch wie im Artikelbild oben zu sehen jeder Eintrag zwei unter seiten haben, oder?

MfG Daniel

Antworten
Avatar von André Köbel

André Köbel 30. Juni 2013 um 14:22

Hallo Daniel,

nein, nein – das Artikelbild bitte nicht falsch deuten. Das wäre die „schlechte“ Methode, wenn du per Hand jeder Seite eine Unterseite zuweisen müsstest.

Wir haben den Artikel aufgrund der Arbeit an einem Kundenprojekt (Spielemagazin) veröffentlicht.

Speziell in diesem Fall ist es so, dass wir diverse Post Types haben:
– Spiele, News, Reviews, Screenshots, Trailer, etc…

Spiele ist hierbei der primäre Post Type und wird (z.B.) über „domain.de/spiele/battlefield-3/“ aufgerufen.

Wird nun eine News zu diesem Spiel erstellt und es wird mit dem Spiel verknüpft, so erscheint auf der Seite des Spiels ein neuer Tab/Link, aufrufbar über „domain.de/spiele/battlefield-3/news/“ wo alle News aufgelistet werden, die diesem Spiel zugeordnet wurden. In dem Fall ist „news“ die virtuelle Unterseite, wird aber im Backend nirgends angezeigt und lediglich über das Template (single-POSTTYPE-FAKEPAGE.php) generiert.

Man könnte natürlich auch das Ganze so automatisieren, dass wenn du eine neue Seite anlegst, automatisch X Unterseiten zu dieser Seite erzeugt werden, aber das wäre – speziell in unserem Fall – bei über 1000 Spielen „ein klein wenig“ unübersichtlich und zeitgleich nicht so funktional wie die von uns vorgestellte Lösung.

Wenn du aber eher nach der angesprochenen Lösung suchst, automatisch beim Erstellen von einer Seite eine Unterseite anzulegen, dann schau mal hier: http://wordpress.stackexchange.com/questions/85827/automatically-create-child-pages-when-saving-a-parent-page.

Hoffe ich konnte dir weiterhelfen, ansonsten einfach nochmal nachhaken. ;)

Gruß
André

Antworten
Avatar von Daniel

Daniel 30. Juni 2013 um 16:02

Hallo André,

du konntest mir in sofern auf jeden Fall weiter helfen als das du mir eine neue interessante Funktion aufgezeigt hast – danke dafür.

Was ich suchte war im Grunde nur die Möglichkeit CPT mit Unterseiten zu nutzen.
Laut Codex „‚page-attributes‘ (menu order, hierarchical must be true to show Parent option)“
hierarchical war true und capability_type war page – demzufolge sollte das funktionieren, tat es aber bis heute nicht.
Zu sehen war nur die Menu Reihenfolge, keine Elternseiten.
Ich vermute es war ein cache problem, denn nun geht es – it´s magic?

Gruß,
Daniel

Antworten
Avatar von André Köbel

André Köbel 1. Juli 2013 um 14:01

Hey Daniel,

ja, manchmal gibts doch die komischten Resultate.

Was meinst du wie oft ich etwas mache, es geht nicht, ich mach es anders, es geht nicht, ändere es wieder auf den 1. Zustand und es geht.

Alles muss man dann wohl doch nicht verstehen. ;)

Gruß
André

Antworten
Avatar von wb

wb 14. Juli 2013 um 15:03

leider bricht bei mir alles zusammen, wp geht nicht mehr.
Mein Post_type habe ich so angelegt:
function post_type_projects() {
register_post_type( ‚projects‘,
array(
‚label‘ => __(‚Projects‘),
‚public‘ => true,
’show_ui‘ => true,
‚publicly_queryable‘ => true,
‚query_var‘ => true,
‚rewrite‘ => true,
‚hierarchical‘ => true,
’supports‘ => array(
‚title‘,
‚editor‘,
‚post-thumbnails‘,
‚custom-fields‘,
‚revisions‘)
)
);
}
add_action(‚init‘, ‚post_type_projects‘);

Rest habe ich von dir kopiert, aber nix geht :( Weist du mehr?

Antworten
Avatar von Christian Lang

Christian Lang 15. Juli 2013 um 19:27

Hallo,

schick mir doch mal bitte eine E-Mail an mail@endcore.com.

Ich melde mich bei Zeit dann bei dir und schaue mir das mal genauer an, so Wild kann’s nicht sein :-)

Gruß
Christian

Antworten
Avatar von Kevin

Kevin 10. Mai 2015 um 14:12

Moin, interessantes Snippet, ich habe eine bestehende Seite für die ich das gut gebrauchen könnte. bzw. gerne einbauen würde.
Allerdings läuft die Seite ohne CPT sondern unter den normalen Beiträgen/Artikel..

Wäre dies hier nun auch möglich?
Ich könnte dann für die News und Reviews ja jeweils ein CPT anlegen…

Vile Grüße und schönen Sonntag,
K.

Antworten
Avatar von Christian

Christian 11. Mai 2015 um 7:57

Hi Kevin,

puh. Du kannst es mal versuchen, theoretisch sind ja Posts auch nur ein Post Type (post). Wenn du das Snippet entsprechend abänderst, sollte es klappen.

Gruß
Christian

Antworten
Avatar von Michael

Michael 24. Mai 2015 um 2:20

Hi. Danke erstmal für den Beitrag. Ich denke dass ich genau nach so einer Lösung gesucht habe. Leider kenne ich mich noch nicht sehr gut mit wordpress aus und hab hier gerade noch ein paar Schwierigkeiten. Ich habe den Code in die functions.php eingefügt. Normalerweise müsste doch jetzt schon der Url abrufbar sein oder? Ich habe auch eine entsprechende single-autos-details.php mit einem echo-Text Befehl zum Test angelegt, aber der Url führt mich nur zu den Infos von autos/audi. Ehrlich gesagt weiss ich auch nicht, wo ich das benutzerdefinierte Feld verlinken muss. (Ich arbeite übrigens mit Advanced Custom Fields)?? Sorry für meine laienhaften Fragen, aber aller an Anfang ist ja bekanntlich schwer :) Gruß Michael

Antworten
Avatar von Christian

Christian 26. Mai 2015 um 10:09

Hey,

hast du die Permalinks mal neu gespeichert?

Antworten
Avatar von Michael

Michael 25. Mai 2015 um 0:50

Hallo. Danke erstmal für diesen hilfreichen Post :) Das hat mir sehr geholfen. Ich hätte da nur eine Frage: Ich habe jetzt drei virtuelle Unterseiten angelegt, aber es funktioniert nur eine davon. An einem Tippfehler liegt es nicht, habe jetz schon etliche Male alles überprüft. Ich habe in der function den folgenden unterstrichenen Teil weggelassen …$matches[1]& #038 ;fpage=‘ . $slug;….. und auf meiner single-autos.php folgenden code hinzugefügt: „$current_vp = get_query_var(‚fpage‘);“. Sonst alles nach deiner Anweisung. Könnte das was mit den Voraussetzungen bzw. Ressourcen zu tun haben. Wäre sehr dankbar wenn Du mir nen Tipp geben könntest.

Antworten
Avatar von Christian

Christian 26. Mai 2015 um 10:12

Hi Michael,

das & muss durch ein „&“-Zeichen ersetzt werden. Der Artikel ist schon älter und die Formatierung wurde leider beim Relaunch etwas verzerrt.

Antworten
Avatar von Peer

Peer 28. September 2015 um 10:15

Danke für den Artikel. Bekomme nur leider immer ein „seite nicht gefunden“…. habe Permalinks schon aktualisiert. Hast Du da eine Idee?

Antworten
Avatar von André

André 5. Oktober 2015 um 10:34

Hast du etwas am Code angepasst? Dann vermutlich hier irgendwo einen Fehler drin. Ansonsten kopier den Code erstmal nur 1:1 und teste es damit. :)

Antworten

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

Du kannst folgende HTML-Tags benutzen: <strong>, <em>, <u>, <a href="">, <del>, <ul>, <ol>, <blockquote>. Für Code benutze bitte pastebin.com und kopiere den Link in dein Kommentar.
*
*