WordPress-Plugin, das virtuelle Seiten generiert und Designvorlagen verwendet

Lesezeit: 9 Minuten

Benutzeravatar von Brian C
Brian C

Ich muss in der Lage sein, gefälschte/virtuelle/dynamische Seiten basierend auf einer URL wie zu generieren http://www.mycinema.com/wpcinema/movie/MOVIEID Filme für Kinos mit Informationen zum Film und Live-Session-Feed-Informationen anzeigen zu können.

Nachdem ich viele Stunden mit der Recherche verbracht habe, scheint nicht viel darüber geschrieben zu sein, wie man virtuelle Seiten in WordPress erstellt, also werde ich meine Erfahrungen aufschreiben, nachdem ich das gelöst habe!

Bisher ist geplant, die beiden Filter zu verwenden – template_redirect, um das Template auf das page.php-Template des aktuellen Plugins zu setzen, und the_content, um den Inhalt einzufügen. Die Idee ist, die Vorlage des Themas zu verwenden, damit sich das Seitenthema gut in die Website einfügt.

(Ich habe diesen Ansatz von diese ausgezeichnete 2012-Seite von Xavi Esteve).

Ich habe zwei Probleme:

  1. Was ist der beste und kugelsicherste Weg, dies zu tun? Verwende ich den falschen Ansatz? Mein Gedanke war, dass die Verwendung der Vorlage des aktuellen Themas wahrscheinlich die beste aktuelle Passform für den Stil der Website bietet.

  2. TwentyTwelve scheint den Filter the_content nicht in dem Kontext aufzurufen, in dem ich ihn verwende. Ich vermute, dass ich etwas falsch mache, aber ich kann den Fehler nicht finden. Dies hängt wahrscheinlich eng mit Frage 1 zusammen. TwentyTwelve ruft definitiv the_content für eine normale Seite auf, und selbst ein frühes add_filter() löst in meinem Code nicht aus.

Ich habe gestern get_template_part() entdeckt und mich gefragt, ob ich das verwenden sollte, anstatt manuell im untergeordneten Ordner und dann im übergeordneten Ordner zu suchen und ein Include auszuführen.

Ich würde nicht fragen, aber ich bin mit meinem Latein am Ende, nachdem ich ausgiebig gegoogelt habe, möglicherweise nach den falschen Suchbegriffen.

Ich habe benutzerdefinierte Beitragstypen in Betracht gezogen, aber es gibt verschiedene Komplexitäten (einschließlich Inhalt, der sich alle paar Minuten ändern kann), was bedeutet, dass eine dynamisch generierte Seite viel besser funktioniert.

Dies ist ein Auszug aus dem Code, den ich geschrieben habe, um das Problem weiter zu erklären:

add_action('parse_request', array(&$this, 'vm_parse_request'));

function vm_parse_request( &$wp )
{
    global $wp;
    if (empty($wp->query_vars['pagename']))
        return; // page isn't permalink

    $p = $wp->query_vars['pagename'];

    if (! preg_match("#wp-cinema/movie/([^/]+)#", $p, $m))
        return;

    // setup hooks and filters to generate virtual movie page
    add_action('template_redirect', array(&$this, 'vm_template_redir'));
    add_filter('the_content', array(&$this, 'vm_the_content'));
}

function vm_template_redir()
{
    // Reset currrently set 404 flag as this is a plugin-generated page
    global $wp_query;
    $wp_query->is_404 = false;

    $template="page.php";

    include(STYLESHEETPATH."/page.php"); // child
    // parent case left out for brevity

    exit;
}


function vm_the_content($content)
{
    return "my new content (actually generated dynamically)";
}

Dies wird in WordPress immer häufiger vorkommen – kann jemand Vorschläge machen oder helfen? Alles wird sehr geschätzt.

  • Hallo Brian, ich frage mich, ob ich virtuelle Seiten auf meine Frage anwenden kann wordpress.stackexchange.com/questions/110118/… Was denken Sie?

    – Radek

    15. August 2013 um 6:26 Uhr

  • Radek – obwohl ich es nicht getestet habe, glaube ich, dass Sie es könnten, wenn Sie die Startseite auf etwas anderes als eine vorhandene Seite einstellen können. Oder Sie könnten meinen Code verwenden, um ihn zu überschreiben.

    – Brian C

    20. Februar 2014 um 1:17 Uhr

Benutzeravatar von Brian C
Brian C

(Update am Fuß des Artikels, einschließlich Link zu verbessertem Arbeitscode-Kern)

Ich wollte eine Antwort darauf posten, da anscheinend KEINE der Fragen zu virtuellen WordPress-Seiten hier Antworten hatte! Und es war viel Blut im Spiel, um die Antwort auf diese Frage zu finden, sie zu testen und sicherzustellen, dass sie gut funktioniert. Hoffentlich erspart das ein paar anderen den Schmerz, den ich durchgemacht habe …

Es stellt sich heraus, dass im Jahr 2013 mit WordPress 3.5.2+ (jetzt 3.6 seit einer Woche) die oben erwähnte Lösung von Xavi Esteve nicht mehr funktioniert, da sich WordPress weiterentwickelt hat, verdammt.

Wenn man die Methode template_redirect oben allein verwendet, besteht das Problem darin, dass es für WordPress keinen Seiten-/Beitragsinhalt gibt und daher viele Themen the_content() nicht aufrufen werden, daher wird mein Code für den the_content-Filter nie aufgerufen.

Heutzutage scheint die beste Lösung zu sein, sich in den ‘the_posts’-Filter einzuklinken und eine Pseudo-Seite zurückzugeben, die jedoch an sich kein Thema hat.

Die Lösung für das fehlende Thema bestand darin, dies mit einem Teil von Xavi Esteves Ansatz zu kombinieren, um mir zu ermöglichen, die Vorlage zu ändern, die zum Erstellen der Seite verwendet wird.

Dieser Ansatz sollte für die meisten, wenn nicht alle WordPress-Themen sofort funktionieren, was mein Ziel war, und es funktioniert wirklich gut mit den Themen, die ich bisher getestet habe.

Ich habe den von Dave Jesch auf dieser Seite dokumentierten Ansatz verwendet (es gibt andere Versionen davon, aber Dave ist der einzige, der es sorgfältig erklärt hat, danke Dave!): http://davejesch.com/wordpress/wordpress-tech/creating-virtual-pages-in-wordpress/

Ich habe hier auch viel Schmerz durchgemacht, da der Abschnitt mit den Kommentaren von WordPress in einigen Themen unten auf der Seite angezeigt wurde. Die Lösung dafür wird in der oben verlinkten Datei erscheinen und ist wahrscheinlich nicht im Umfang dieser speziellen Lösung enthalten.

Um eine Warnung mit WordPress 3.5.2+ zu verhindern, musste ich auch ein Beitragsmitglied hinzufügen:

 $post->ancestors = array();

Diese Lösung wird im wp-cinema WordPress-Plugin (file Ansichten.php wenn Sie sich etwas funktionierenden Code schnappen möchten, sollte in den nächsten Wochen eingecheckt werden). Wenn es Probleme mit dem Ansatz gibt, werde ich diese Datei aktuell halten, da sie Teil eines größeren Projekts ist.

Die vollständige Arbeitslösung ist unten. Dies ist ein Auszug aus einem viel längeren Codestück, das auch das Erscheinen von Kommentaren usw. verhindert (siehe oben angegebenen Link). Der Code:

add_action('parse_request', 'vm_parse_request');


// Check page requests for Virtual movie pages
// If we have one, generate 'movie details' Virtual page.
// ...
//
function vm_parse_request(&$wp)
{
    if (empty($wp->query_vars['pagename']))
       return; // page isn't permalink

    $p = $wp->query_vars['pagename'];

    if (! preg_match("#wp-cinema/movie/([^/]+)#", $p, $m))
       return;

    // setup hooks and filters to generate virtual movie page
    add_action('template_redirect', 'vm_template_redir');

    $this->vm_body = "page body text";

    add_filter('the_posts', 'vm_createdummypost');

    // now that we know it's my page,
    // prevent shortcode content from having spurious <p> and <br> added
    remove_filter('the_content', 'wpautop');
}


// Setup a dummy post/page 
// From the WP view, a post == a page
//
function vm_createdummypost($posts)
{
    // have to create a dummy post as otherwise many templates
    // don't call the_content filter
    global $wp, $wp_query;

    //create a fake post intance
    $p = new stdClass;
    // fill $p with everything a page in the database would have
    $p->ID = -1;
    $p->post_author = 1;
    $p->post_date = current_time('mysql');
    $p->post_date_gmt =  current_time('mysql', $gmt = 1);
    $p->post_content = $this->vm_body;
    $p->post_title = $this->vm_title;
    $p->post_excerpt="";
    $p->post_status="publish";
    $p->ping_status="closed";
    $p->post_password = '';
    $p->post_name="movie_details"; // slug
    $p->to_ping = '';
    $p->pinged = '';
    $p->modified = $p->post_date;
    $p->modified_gmt = $p->post_date_gmt;
    $p->post_content_filtered = '';
    $p->post_parent = 0;
    $p->guid = get_home_url("https://stackoverflow.com/" . $p->post_name); // use url instead?
    $p->menu_order = 0;
    $p->post_type="page";
    $p->post_mime_type="";
    $p->comment_status="closed";
    $p->comment_count = 0;
    $p->filter="raw";
    $p->ancestors = array(); // 3.6

    // reset wp_query properties to simulate a found page
    $wp_query->is_page = TRUE;
    $wp_query->is_singular = TRUE;
    $wp_query->is_home = FALSE;
    $wp_query->is_archive = FALSE;
    $wp_query->is_category = FALSE;
    unset($wp_query->query['error']);
    $wp->query = array();
    $wp_query->query_vars['error'] = '';
    $wp_query->is_404 = FALSE;

    $wp_query->current_post = $p->ID;
    $wp_query->found_posts = 1;
    $wp_query->post_count = 1;
    $wp_query->comment_count = 0;
    // -1 for current_comment displays comment if not logged in!
    $wp_query->current_comment = null;
    $wp_query->is_singular = 1;

    $wp_query->post = $p;
    $wp_query->posts = array($p);
    $wp_query->queried_object = $p;
    $wp_query->queried_object_id = $p->ID;
    $wp_query->current_post = $p->ID;
    $wp_query->post_count = 1;

    return array($p);
}


// Virtual Movie page - tell wordpress we are using the page.php
// template if it exists (it normally will).
//
// We use the theme page.php if we possibly can; if not, we do our best.
// The get_template_part() call will use child theme template if it exists.
// This gets called before any output to browser
//
function vm_template_redir()
{
    // Display movie template using WordPress' internal precedence
    //  ie: child > parent; page-movie.php > page.php
    //  this call includes the template which outputs the content
    get_template_part('page', 'movie');

    exit;
}

Übrigens ist es wichtig zu sagen, dass ich das Gefühl habe, dass dies ein ziemlicher Hack ist, und ich würde gerne wissen, wie es besser gemacht werden könnte. Außerdem würde ich gerne sehen, wie WordPress ins Schwarze trifft und eine API zum Generieren gefälschter Seiten bereitstellt. (Ich vermute, sie haben ideologische Gründe, warum sie es nicht tun, aber es wäre schön, ihre Lösungen dafür, auch wenn sie alternativ sind, ausführlich erklärt zu sehen); Ich persönlich habe das Gefühl, dass es Fälle gibt, in denen ich mich nicht in die Site eines Benutzers einmischen möchte, nur um Seiten zu generieren.

UPDATE Februar 2014: Ich habe dies in eine Klasse abstrahiert, die für die meisten Anwendungen ausreichende Flexibilität bieten sollte: https://gist.github.com/brianoz/9105004

  • Seitdem habe ich dies in eine Klasse umgewandelt, um mehrere virtuelle Seiten zu verwalten. Die Klasse ruft eine bereitgestellte Inhaltsfunktion auf, wenn ein regulärer Ausdruck gefunden wird. Wenn ich mich diesbezüglich sicher fühle, ersetze ich den obigen Link durch einen Link zur Klassendatei (die ein Beispiel enthält). Prod mich, wenn du es brauchst und ich habe es vergessen! 🙂

    – Brian C

    13. August 2013 um 2:00 Uhr

  • Dies ist eine interessante Methode. Ich habe versucht, etwas Ähnliches für eine Weile mit mäßigem Erfolg zu tun. Haben Sie einen Link zu der Klassendatei, die Sie zur Verfügung gestellt haben?

    – Das Salz

    11. Januar 2014 um 17:28 Uhr

  • Entschuldigung, ja; Ich hatte vergessen, dass ich es schon getan hatte. Das Wesentliche ist hier (aktualisierter Artikel auch): gist.github.com/brianoz/9105004 Dies sollte flexibel genug sein, um mit den meisten Anwendungen zu arbeiten, Feedback ist willkommen.

    – Brian C

    20. Februar 2014 um 1:12 Uhr


  • Die auf Gist verlinkte Klasse funktionierte perfekt für meinen Anwendungsfall (Erstellen “virtueller” Seiten basierend auf dem ersten Teil des URL-Pfads). Es lohnt sich, die Kommentare auf der Gist-Seite durchzulesen – dort müssen Sie drei Codezeilen ändern, damit sie funktioniert.

    – Andreas Sauder

    22. August 2015 um 9:07 Uhr

1397700cookie-checkWordPress-Plugin, das virtuelle Seiten generiert und Designvorlagen verwendet

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy