Definieren Sie eine benutzerdefinierte Seitenvorlage ohne eigene PHP-Datei

7

Gibt es eine Möglichkeit, eine Seitenvorlage aus einer Funktion / einem Filter / einem Hook zu definieren, ohne dass eine .php-Datei mit dem Kommentar oben auf der Seite vorhanden ist, um den Vorlagennamen zu deklarieren?


Zum Beispiel, anstatt dies zu tun:

some-custom-page-template.php

/**
* Template Name: Some Custom Page Template
*/

another-custom-page-template.php

/**
* Template Name: Another Custom Page Template
*/

Ich frage mich, ob ich so etwas tun kann:

functions.php

wp_some_function_to_define_templates( 'Some Custom Page Template' );
wp_some_function_to_define_templates( 'Another Custom Page Template' );

BEARBEITEN : Ich schreibe ein komplexes und experimentelles WP-Thema. Es ist so objektorientiert, wie es WP zulässt. Ich habe Controller-Klassen, um zu entscheiden, was auf jeder Seite angezeigt werden soll, DAO-Klassen, um Daten aus DB, Twig abzurufen Vorlagen zum Generieren der Ansichten und so weiter ...

Ich habe den Code so weit verbreitet, dass meine Seitenvorlagen nur noch eine Codezeile sind, in der ich einen Controller aufrufe und ihn die Arbeit machen lasse, um schließlich eine Zweigvorlage zu rendern. Also habe ich beschlossen, diesen Aufruf an den Controller in den template_includeFilter zu verschieben, damit ich nicht einmal Code in die Seitenvorlagen einfügen muss ...

Ich werde möglicherweise Seitenvorlagen entfernen, aber ich brauche sie immer noch, um Seiten irgendwie zu gruppieren , um einige erweiterte benutzerdefinierte Feldgruppen für sie festzulegen usw.

Am Ende hatte ich ungefähr 15 PHP-Dateien, die oben nur einen Kommentar mit einem Vorlagennamen enthalten. Genau das möchte ich vermeiden, indem ich diese Vorlagen aus einer Funktion definiere ...

Versuche ich das Rad neu zu erfinden ? Vielleicht in gewissem Sinne, aber ich denke, es wird ein wirklich cooles Thema, sehr wartbar und modifizierbar ...

MikO
quelle
Verfolgten Sie diesen Mechanismus mit dem Vorlagennamen in Kommentar? Und was ist daran falsch?
Pratik
@PratikJoshi, ich habe meine Frage so bearbeitet, dass sie eine richtige Erklärung enthält, wenn Sie einen Blick darauf
werfen
Die einzige Funktion für die Seitenvorlagen besteht darin, das Vorlagenauswahlfeld im Backend auszufüllen.
s_ha_dum
@s_ha_dum, im Grunde ja, aber das erlaubt mir, Seiten zu gruppieren , so dass ich ACF- Feldgruppen für alle festlegen, denselben Controller für die Verarbeitung ihrer Daten verwenden kann (mit einigen Parametern, die aus dem Seitennamen stammen), dieselbe Twig-Vorlage verwenden kann für sie und so weiter ...
MikO
1
Die Funktion, mit der das Meta-Feld für Seitenvorlagen gefüllt wird, kann nicht gefiltert werden. Da Sie es jedoch nicht so verwenden, wie es beabsichtigt war, können Sie einfach Ihr eigenes Meta-Feld hinzufügen und es mit den gewünschten Optionen füllen.
Milo

Antworten:

6

WordPress liest die Vorlagen aus den Datei-Headern und legt sie dann im Cache ab. Verwenden Sie wp_cache_set()nad, einen Schlüssel, der vom MD5-Stylesheet-Ordner abgeleitet ist.

Wenn Sie also nur diesen Cache überschreiben, können Sie die gewünschten Vorlagen anzeigen. Um diesen Cache zu überschreiben, müssen wir wp_cache_set()erneut mit demselben Schlüssel aufrufen .

Lassen Sie uns zunächst eine Funktion schreiben, die die Vorlagen abruft, die wir anzeigen möchten. Es gibt viele Möglichkeiten, Vorlagen festzulegen: Option, Konfigurationsdatei, Filter oder eine Kombination davon:

function get_custom_page_templates() {
  $templates = array();
  // maybe by options? --> $templates = get_option( 'custom_page_templates' );
  // maybe by conf file? --> $templates = include 'custom_page_templates.php';
  return apply_filters( 'custom_page_templates', $templates );
}

Danach müssen wir die Vorlagen innerhalb der Seitenbearbeitung abrufen, kurz nachdem WordPress den Cache gespeichert hat. Außerdem müssen wir sie erneut erhalten, wenn das Bearbeitungsformular veröffentlicht wird, um das Speichern zu ermöglichen.

Wir können den 'edit_form_after_editor'Haken für den ersten Bereich 'load-post.php'und 'load-post.new'für den zweiten verwenden:

add_action( 'edit_form_after_editor', 'custom_page_templates_init' );
add_action( 'load-post.php', 'custom_page_templates_init_post' );
add_action( 'load-post-new.php', 'custom_page_templates_init_post' );

function custom_page_templates_init() {
  remove_action( current_filter(), __FUNCTION__ );
  if ( is_admin() && get_current_screen()->post_type === 'page' ) {
    $templates = get_custom_page_templates(); // the function above
    if ( ! empty( $templates ) )  {
      set_custom_page_templates( $templates );
    }
  }
}

function custom_page_templates_init_post() {
  remove_action( current_filter(), __FUNCTION__ );
  $method = filter_input( INPUT_SERVER, 'REQUEST_METHOD', FILTER_SANITIZE_STRING );
  if ( empty( $method ) || strtoupper( $method ) !== 'POST' ) return;
  if ( get_current_screen()->post_type === 'page' ) {
    custom_page_templates_init();
  }
}

Als letztes müssen wir die set_custom_page_templates()Funktion schreiben, die den Cache bearbeitet, um unsere Vorlagen einzuschließen, und dabei sicherstellen, dass alle durch Dateikopfzeilen definierten Vorlagen zusammengeführt werden:

function set_custom_page_templates( $templates = array() ) {
  if ( ! is_array( $templates ) || empty( $templates ) ) return;
  $core = array_flip( (array) get_page_templates() ); // templates defined by file
  $data = array_filter( array_merge( $core, $templates ) );
  ksort( $data );
  $stylesheet = get_stylesheet();
  $hash = md5( get_theme_root( $stylesheet ) . '/' . $stylesheet );
  $persistently = apply_filters( 'wp_cache_themes_persistently', false, 'WP_Theme' );
  $exp = is_int( $persistently ) ? $persistently : 1800;
  wp_cache_set( 'page_templates-' . $hash, $data, 'themes', $exp );
}

Wenn dieser Code ausgeführt wird, können Sie benutzerdefinierte Vorlagen nur mit der in der get_custom_page_templates()Funktion verwendeten Methode einrichten. Hier verwende ich den Filter:

add_filter( 'custom_page_templates', function( $now_templates ) {

  $templates = array(
    'some-custom-page-template' => 'Some Custom Page Template',
    'another-custom-page-template' => 'Another Custom Page Template' ,
  );

  return array_merge( $now_templates, $templates );

} );

Und du bist fertig.

gmazzap
quelle
Genialer Trick! Es ist klar, dass Sie sich in die Eingeweide von WP vertieft haben :) Wie auch immer, ich denke, dass es wahrscheinlich keine sehr gute Idee ist, jedes Mal so viel Arbeitslast hinzuzufügen, wenn Sie eine Seite laden möchten ... Ich denke, ich sollte es besser behalten Meine Vorlagendateien mit einer Codezeile, ich werde sie einfach in einen Unterordner legen und sie vergessen ... glaubst du nicht?
MikO
1
@MikO Nicht wirklich. Diese Funktion wirkt hauptsächlich auf das Backend, auf das Frontend tut man nichts. Darüber hinaus ist das Lesen einer Dateiformatdiskette und das Analysieren der Kommentarüberschrift langsamer als nur das Aktualisieren eines Arrays. Wenn Sie eine Datei mit einer hohen Anzahl von Vorlagen testen, werden Sie feststellen, dass der Arbeitsablauf für Dateien ziemlich langsam ist.
gmazzap
Das hat bei mir nicht funktioniert. Gibt es einen neuen Weg, dies zu tun?
Mrmadhat
Ich habe ein Plugin basierend auf diesem erstellt , um dies zu tun.
sicherlich
2

Wenn ich dich verstehe, kannst du das mit dem template_includeHaken machen. Zum Beispiel:

add_filter( 'template_include', 'phpless_template');
function phpless_template( $template ) {  
  get_header();
  // some php
  get_footer();
  die;
}
s_ha_dum
quelle
Guter Trick, aber nicht das, wonach ich suche ... Wenn Sie eine Sekunde warten, schreibe ich eine BEARBEITUNG in meine Frage, weil das Szenario etwas komplex ist
MikO
0

Ich schlage Ihnen eine einfachere Problemumgehung vor:

  1. Definieren Sie in Ihrer Konfigurations- / Funktions- / Indexdatei eine Konfigurationsvariable $config_template = false;(*).
  2. Erstellen Sie einen Ordner "include" (wahrscheinlich haben Sie bereits einen)
  3. Legen Sie dort die Dateien some-custom-page-template.php und another-custom-page-template.php ab
  4. Weisen Sie in diesen Dateien einfach $ config_template einen Wert zu und benötigen Sie dann die Seite, die Sie zum Rendern der Schleife verwenden - zum Beispiel: $config_template = 'some-custom-page'; require( "../index.php" );
  5. In dieser Datei (index.php) können Sie basierend auf dem Wert von $ config_template möchten, dass Sie möchten

Mit dieser Methode erzwingen Sie nicht den normalen Workflow von WP (dies ist nie eine gute Idee), aber Sie halten Ihr Projekt ausreichend sauber.

(*) Wahrscheinlich verwenden Sie bereits einige Objekteigenschaften, um Ihre Konfigurationen zu verwalten. Dort legen Sie die Variable $ config_template ab.

Marco Panichi
quelle