Ich habe einen benutzerdefinierten Beitragstyp paper
in meinem WordPress-Plugin definiert, den ich zusammen mit Standardbeiträgen in der Hauptabfrage zeige:
function add_custom_post_types_to_query( $query ) {
if ( is_home() && $query->is_main_query() )
$query->set( 'post_type', array( 'post', 'paper' ) );
// As was pointed out by Ihor Vorotnov this return is not necessary.
// return $query;
}
add_action( 'pre_get_posts', 'add_custom_post_types_to_query' );
Ich konnte auch eine benutzerdefinierte single-paper.php
-Vorlage aus dem Plugin-Verzeichnis für meinen Beitragstyp registrieren:
function get_custom_post_type_single_template( $single_template ) {
global $post;
if ( $post->post_type == 'paper' ) {
$single_template = dirname( __FILE__ ) . '/single-paper.php';
}
return $single_template;
}
add_filter( 'single_template', 'get_custom_post_type_single_template' );
Ich möchte etwas Ähnliches für die Vorlage content-____.php
tun, die von meinem Thema (onepress
) verwendet wird, um zu steuern, wie meine Beiträge in der Hauptabfrage angezeigt werden.
Der index.php
des Themas sagt sogar:
<?php /* Start the Loop */ ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php
/*
* Include the Post-Format-specific template for the content.
* If you want to override this in a child theme, then include a file
* called content-___.php (where ___ is the Post Format name) and that will be used instead.
*/
get_template_part( 'template-parts/content', get_post_format() );
?>
<?php endwhile; ?>
aber ich möchte lieber kein untergeordnetes Thema dafür implementieren und den gesamten Code, der sich auf den benutzerdefinierten Beitragstyp bezieht, im Plugin behalten.
Gibt es eine Möglichkeit, einen Filter so hinzuzufügen, dass get_template_part( 'template-parts/content', get_post_format() );
eine benutzerdefinierte Vorlage verwendet, die von meinem Plugin für paper
Posts bereitgestellt wird, und die Standardvorlage des Themas für normale Posts?
Ich habe verschiedene Varianten des Codes ausprobiert, den ich oben für den 'single_template'
verwendet habe, aber ohne Erfolg.
Leider hat get_template_part()
function keinen geeigneten Filter, um das zu erreichen, was Sie wollen. Es ist möglich, den Aktions-Hook get_template_part_{$slug}
zum Einfügen von Vorlagenteilen zu verwenden. Ohne Änderungen an Ihrem Thema oder einem untergeordneten Thema wird der ursprüngliche Vorlagenteil jedoch trotzdem hinzugefügt. Auf diese Weise können Sie vorhandene Schablonenteile nicht ersetzen.
Sie können jedoch das gewünschte Ergebnis erzielen, indem Sie eine der folgenden Optionen wählen:
Wenn Sie nur den Stil für den benutzerdefinierten Beitragstyp paper
ändern möchten, können Sie einfach die von WordPress generierte CSS-Klasse verwenden. Jedes Standardthema in WordPress generiert $post_type
- und type-{$post_type}
-CSS-Klassen für den Beitragsinhalt. Der benutzerdefinierte Beitragstyp paper
hat beispielsweise paper
& type-paper
CSS-Klassen, und der allgemeine post
hat post
und type-post
CSS-Klassen. Auch auf der Homepage befindet sich die CSS-Klasse home
im Body. Um paper
-Einträge auf der Homepage auszurichten, können Sie die folgenden CSS-Regeln verwenden:
body.home .type-paper {
/* Custom CSS for paper entries in the home page */
}
Wenn Ihnen die Standard-CSS-Klassen nicht ausreichen, können Sie CSS-Klassen auch mit dem post_class
filter-Hook in Ihrem Plugin ändern (hinzufügen/entfernen). So was:
add_filter( 'post_class', 'paper_post_class' );
function paper_post_class( $class ) {
if ( get_post_type() === 'paper' && is_home() ) {
// remove these classes
$remove = array( 'css-class-to-remove', 'another-class-to-remove' );
$class = array_diff( $class, $remove );
// add these classes
$add = array( 'custom-paper', 'my-paper-class' );
$class = array_merge( $add, $class );
}
return $class;
}
Auf diese Weise können Sie nicht benötigte CSS-Klassen für paper
-Einträge entfernen und neue CSS-Klassen für paper
-Einträge hinzufügen, ohne die Designdateien zu ändern. Verwenden Sie dann diese CSS-Klassen, um den Stil von paper
-Einträgen nach Bedarf zu ändern.
Wenn Ihr gewünschter Stil nicht nur durch Targeting von CSS-Klassen geändert werden kann, können Sie die Template-Teile auch über Ihr Plugin ändern. Da das Ersetzen von durch get_template_part()
hinzugefügten Vorlagenteilen durch Hooks nicht möglich ist, müssen Sie die Vorlage so ändern, dass Sie den Aufruf von get_template_part()
über das Plugin ändern können.
Zu diesem Zweck können Sie Ihre Hook-Funktion auf pre_get_posts
ausrichten und mit template_include
filter hook die Homepage-Vorlage wie folgt ändern:
function add_custom_post_types_to_query( $query ) {
if ( is_home() && $query->is_main_query() ) {
$query->set( 'post_type', array( 'post', 'paper' ) );
// now also change the home page template, but only when this condition matches
add_filter( 'template_include', 'wpse258844_custom_template', 999 );
}
}
add_action( 'pre_get_posts', 'add_custom_post_types_to_query' );
Verwenden Sie dann den folgenden CODE (ändern Sie ihn nach Bedarf):
// for better file management, use a separate "theme-{$theme_name_slug}" directory within your plugin directory
// so if the active theme name is "OnePress", the directory name will be "theme-onepress"
// This will save you a ton of headache if you change the theme,
// as different themes may use different function calls within the templates, which other themes may not have
define( 'wpse258844_TEMPLATE_DIR', plugin_dir_path( __FILE__ ) . sprintf( 'theme-%s/', sanitize_title( wp_get_theme() ) ) );
function wpse258844_custom_template( $template ) {
// this file will replace your homepage template file
$index_paper = wpse258844_TEMPLATE_DIR . 'custom-home.php';
// file_exists() check may need clearing stat cache if you change file name, delete the file etc.
// Once you are done, comment out or remove clearstatcache(); in production
clearstatcache();
if ( file_exists( $index_paper ) ) {
$template = $index_paper;
}
return $template;
}
function wpse258844_get_template_part( $slug, $name = null ) {
if( get_post_type() === 'paper' ) {
// just to be consistant with get_template_part() function
do_action( "get_template_part_{$slug}", $slug, $name );
$located = '';
$name = (string) $name;
// file_exists() check may need clearing stat cache if you change file name, delete the file etc.
// Once you are done, comment out or remove clearstatcache(); in production
clearstatcache();
if ( '' !== $name && file_exists( wpse258844_TEMPLATE_DIR . "{$slug}-{$name}.php" ) ) {
$located = wpse258844_TEMPLATE_DIR . "{$slug}-{$name}.php";
}
else if ( file_exists( wpse258844_TEMPLATE_DIR . "{$slug}.php" ) ) {
$located = wpse258844_TEMPLATE_DIR . "{$slug}.php";
}
if ( '' != $located ) {
load_template( $located, false );
return;
}
}
get_template_part( $slug, $name );
}
Sobald du den obigen CODE in deinem Plugin hast (lies die Kommentare im CODE):
Erstellen Sie ein neues Verzeichnis in Ihrem Plugin-Verzeichnis, um die Theme-Vorlagendateien zu speichern, z. theme-onepress
. Dies wird Ihnen in Zukunft helfen, wenn Sie Designänderungen mit einem anderen Thema testen möchten (ich nehme an, das ist der Hauptzweck all dieser Probleme;)).
Erstellen Sie im neuen Verzeichnis theme-onepress
eine Datei mit dem Namen custom-home.php
. Kopieren Sie den CODE der Homepage-Vorlage aus Ihrem Thema (möglicherweise index.php
oder home.php
oder was auch immer Ihr Thema für die Homepage-Vorlage verwendet).
Ändern Sie jetzt in custom-home.php
den gesamten Aufruf von get_template_part
in wpse258844_get_template_part
. Der Parameter muss nicht geändert werden, nur der Funktionsname. Die Funktion wpse258844_get_template_part()
im obigen CODE ist identisch mit der Funktion get_template_part()
und greift auf das Standardverhalten zurück, wenn der benutzerdefinierte Vorlagenteil nicht im Verzeichnis theme-{$theme_name_slug}
(z. B. theme-onepress
) Ihres Plugins gefunden wird.
Ersetzen Sie abschließend die Vorlagenteile, die Sie ersetzen möchten, im Verzeichnis theme-{$theme_name_slug}
Ihres Plugins.
Wenn der ursprüngliche Aufruf beispielsweise get_template_part( 'template-parts/content', get_post_format() )
war und Sie den content.php
-Vorlagenteil ersetzen möchten, platzieren Sie einfach eine Datei mit dem Namen content.php
im theme-onepress/template-parts
-Verzeichnis Ihres Plugins. Das heißt, das Verzeichnis theme-onepress
verhält sich wie ein untergeordnetes Thema für Vorlagenteile - d. H. Einfaches Ersetzen durch Drop-In.
erstelle deine eigene Funktion dafür:
function get_template_part_custom($content_name) {
global $post;
//its paper type?
if ($post->post_type == 'paper') {
//get template-parts/content-paper.php
get_template_part( 'template-parts/content', $content_name );
}else{
//fallback to the default
get_template_part( 'template-parts/content', get_post_format($post) );
}
}
benutze es so:
get_template_part_custom('paper');
wenn der Beitrag vom Typ paper
ist, wird versucht, eine Datei mit dem Namen content-paper.php
in einen Ordner mit dem Namen template-parts
im Stammverzeichnis zu laden. Wenn die Datei nicht vorhanden ist, wird versucht, content.php
zu laden, überprüfen Sie die Vorlagenhierarchie . Ich glaube nicht, dass Sie Ihre Vorlage registrieren müssen single-paper.php
, WordPress wird es für Sie abholen.
BEARBEITEN:
So laden Sie eine Vorlage aus einem Plugin:
//load a custom file from the plugin
add_filter( 'template_include', 'return_our_template');
//Returns template file
function return_our_template( $template ) {
// Post ID
$post_id = get_the_ID();
// For all other Types that arent ours
if ( get_post_type( $post_id ) != 'paper' ) {
return $template;
}
// Else use our custom template
if ( is_single() ) {
return get_custom_template( 'single' );
}
}
//Get the custom template if is set
function get_custom_template( $template ) {
// Get the slug
$template_slug = rtrim( $template, '.php' );
$template = $template_slug . '.php';
// Check if a custom template exists in the theme folder, if not, load the plugin template file
if ( $theme_file = locate_template( array( 'plugin_template/' . $template ) ) ) {
$file = $theme_file;
}
else {
//here path to '/single-paper.php'
$file = PATH_TO_YOUR_BASE_DIR . $template;
}
//create a new filter so the devs can filter this
return apply_filters( 'filter_template_' . $template, $file );
}
Soweit ich aus dem Quellcode ersehen kann, können Sie get_template_part()
nicht so filtern, wie Sie es normalerweise tun würden. Bitte lesen Sie diesen Thread für einige Lösungen.
Hier ist ein weiterer "Hack", um das zu erreichen, wonach gefragt wurde:
Mit dem post format
(nicht zu verwechseln mit dem post type
!) Kann eine benutzerdefinierte Vorlage für einen benutzerdefinierten Beitragstyp verwendet werden. Erinnere dich an die Linie
get_template_part( 'template-parts/content', get_post_format() );
im index.php
beschrieben in der frage. Durch diese Konstruktion laden die meisten Standard-Themes je nach post format
unterschiedliche Vorlagen.
Man kann behaupten, dass alle Beiträge eines bestimmten benutzerdefinierten Beitragstyps, z. B. paper
name__, ein bestimmtes Beitragsformat haben, z. B. aside
name__, indem man aufruft
set_post_format( $post_id, 'aside' )
während der a-Funktion, die in den 'save_post'
-Hook eingebunden ist, und indem Sie so etwas wie hinzufügen
function paper_format_terms( $terms, $post_id, $tax ) {
if ( 'post_format' === $tax && empty( $terms ) && 'paper' === get_post_type( $post_id ) ) {
$aside = get_term_by( 'slug', 'post-format-aside', $tax );
$terms = array( $aside );
}
return $terms;
}
add_filter( 'get_the_terms', 'paper_format_terms', 10, 3 );
zum 'get_the_terms'
hook.
Man kann keine benutzerdefinierten Postformate definieren, aber normalerweise gibt es mindestens ein Postformat, das für nichts anderes verwendet wird. Das "beiseite" -Format kann eine gute Wahl sein.
Ein Standarddesign sucht dann, wenn es auf einen paper
name__-Beitrag stößt, nach der Vorlage .../template-parts/content-aside.php
. Alles, was Sie tun müssen, ist, eine geeignete Vorlage so in das Theme-Verzeichnis zu installieren, dass sie beim Aktualisieren des Themas nicht überschrieben oder gelöscht wird (wir möchten, dass der gesamte Code im Plugin enthalten ist!). Dies kann getan werden, indem eine geeignete Vorlage in das Feld content-aside.php
im Plugins-Verzeichnis eingefügt und wie folgt in `'upgrader_process_complete' 'eingebunden wird
function install_aside_template_on_upgrade( $upgrader_object, $options ) {
if ($options['type'] == 'theme' ) {
$content_aside = plugin_dir_path( __FILE__ ) . 'content-aside.php';
$template_parts_content_aside = get_stylesheet_directory() . '/template-parts/content-aside.php';
copy($content_aside, $template_parts_content_aside);
}
}
add_action( 'upgrader_process_complete', 'install_aside_template_on_upgrade',10, 2);
Auf diese Weise wird der content-aside.php
nach jeder Aktualisierung des Themas in das Themenverzeichnis kopiert.
Denken Sie daran, dass dies ein ziemlich schrecklicher Hack ist und unerwünschte Nebenwirkungen haben kann! Trotzdem dachte ich, dass dies für einige nützlich sein kann ...
Obwohl dies keine genaue Antwort auf die gestellte Frage ist, gibt es noch einen anderen, recht übersichtlichen und einfachen Weg, um etwas Ähnliches zu erreichen, das, wie ich vermute, für viele Leute, die auf dieser Seite landen, die tatsächlich optimale Lösung sein wird. Für mich haben sich die Anforderungen geringfügig geändert, nachdem ich diese Frage gestellt hatte, sodass ich mich am Ende für diese Lösung entschieden habe.
Anstatt ein benutzerdefiniertes Thema zu verwenden, reicht es in vielen Fällen aus, zu ändern, was ein benutzerdefinierter Beitragstyp zurückgibt, wenn die Vorlage des Themas the_excerpt()
aufruft. Dies kann erreicht werden, indem Sie sich wie folgt in den 'the_excerpt'
-Filter einhängen:
function paper_get_the_excerpt ($content) {
global $post;
$post_id = $post->ID;
if ( get_post_type($post_id) === 'paper' ) {
[do whatever you want with $content]
}
return $content;
}
add_filter( 'the_excerpt', 'paper_get_the_excerpt' );
Schön, sauber und einfach und ermöglicht fast so viel Flexibilität wie das Ändern der Vorlage.