Mein Lieblingsteil der Wordpress Vorlagenhierarchie ist die Möglichkeit, schnell Vorlagendateien für Seiten per Slug zu erstellen, ohne die Seite in Wordpress bearbeiten zu müssen, um eine Vorlage auszuwählen.
Wir können dies derzeit tun:
page- {slug} .php
Das möchte ich aber können:
single- {post_type} - {slug} .php
So könnte ich beispielsweise in einem Beitragstyp mit dem Namen review
eine Vorlage für einen Beitrag mit dem Namen "My Great Review" unter single-review-my-great-review.php
erstellen.
Hat das schon mal jemand eingerichtet? single-{post_type}-{slug}.php
Wie Sie in der Erklärung zur Codex Vorlagenhierarchie sehen können, wird single-{$post_type}.php
bereits unterstützt.
Jetzt gibt es gerne ein paar Filter und Hooks im /wp-includes/template-loader.php
.
do_action('template_redirect');
apply_filters( 'template_include', $template )
get_query_template( $type, ... )
mit dem Namen: "$type}_template"
is_*()
.is_single() && $template = get_single_template()
get_query_template( $type, $templates )
aus, wobei $type
single
ist"{$type}_template"
FilterDa wir nur die Hierarchie mit einer Vorlage erweitern möchten, die vor der tatsächlichen "single-{$object->post_type}.php"
-Vorlage geladen wird, werden wir die Hierarchie abfangen und eine neue Vorlage am Anfang des Vorlagen-Arrays hinzufügen .
// Extend the hierarchy
function add_posttype_slug_template( $templates )
{
$object = get_queried_object();
// New
$templates[] = "single-{$object->post_type}-{$object->post_name}.php";
// Like in core
$templates[] = "single-{$object->post_type}.php";
$templates[] = "single.php";
return locate_template( $templates );
}
// Now we add the filter to the appropriate hook
function intercept_template_hierarchy()
{
add_filter( 'single_template', 'add_posttype_slug_template', 10, 1 );
}
add_action( 'template_redirect', 'intercept_template_hierarchy', 20 );
HINWEIS: (Wenn Sie etwas anderes als den Standardobjekt-Slug verwenden möchten) Sie müssen $slug
entsprechend Ihrer Permalink-Struktur anpassen. Verwenden Sie einfach alles, was Sie brauchen, aus dem globalen (object) $post
.
Da der obige Ansatz derzeit nicht unterstützt wird (Sie können nur den absolut lokalisierten Pfad auf diese Weise filtern), finden Sie hier eine Liste der Trac-Tickets:
get_query_template()
einführenNach dem Template Hierarchy image sehe ich keine solche Option.
Also hier ist, wie ich vorgehen würde:
Lösung 1 (meiner Meinung nach am besten)
Erstellen Sie eine Vorlagendatei und ordnen Sie sie der Überprüfung zu
<?php
/*
Template Name: My Great Review
*/
?>
Wenn Sie die Vorlagen-PHP-Datei in Ihr Themenverzeichnis aufnehmen, wird sie als Vorlagenoption auf der Bearbeitungsseite Ihres Beitrags angezeigt.
Lösung 2
Dies könnte wahrscheinlich mit template_redirect
hook erreicht werden.
In der functions.php Datei:
function my_redirect()
{
global $post;
if( get_post_type( $post ) == "my_cpt" && is_single() )
{
if( file_exists( get_template_directory() . '/single-my_cpt-' . $post->post_name . '.php' ) )
{
include( get_template_directory() . '/single-my_cpt-' . $post->post_name . '.php' );
exit;
}
}
}
add_action( 'template_redirect', 'my_redirect' );
EDIT
file_exists
check hinzugefügt
Die Top-Antwort (ab 4 Jahren) funktioniert nicht mehr, aber der WordPress-Codex hat hier die Lösung :
<?php
function add_posttype_slug_template( $single_template )
{
$object = get_queried_object();
$single_postType_postName_template = locate_template("single-{$object->post_type}-{$object->post_name}.php");
if( file_exists( $single_postType_postName_template ) )
{
return $single_postType_postName_template;
} else {
return $single_template;
}
}
add_filter( 'single_template', 'add_posttype_slug_template', 10, 1 );
?>
Ein weiterer Ansatz für die Skalierbarkeit besteht darin, die Dropdown-Funktion für Seitenvorlagen für den Beitragstyp page
für Ihren benutzerdefinierten Beitragstyp zu duplizieren.
Die Vervielfältigung von Code ist keine gute Praxis. Im Laufe der Zeit kann es zu einem starken Aufblähen der Codebasis kommen, wenn es für einen Entwickler sehr schwierig wird, damit umzugehen. Anstatt eine Vorlage für jeden einzelnen Slug zu erstellen, benötigen Sie höchstwahrscheinlich eine Eins-zu-Viele-Vorlage, die anstelle einer Eins-zu-Eins-Post-zu-Vorlage wiederverwendet werden kann.
# Define your custom post type string
define('MY_CUSTOM_POST_TYPE', 'my-cpt');
/**
* Register the meta box
*/
add_action('add_meta_boxes', 'page_templates_dropdown_metabox');
function page_templates_dropdown_metabox(){
add_meta_box(
MY_CUSTOM_POST_TYPE.'-page-template',
__('Template', 'Rainbow'),
'render_page_template_dropdown_metabox',
MY_CUSTOM_POST_TYPE,
'side', #I prefer placement under the post actions meta box
'low'
);
}
/**
* Render your metabox - This code is similar to what is rendered on the page post type
* @return void
*/
function render_page_template_dropdown_metabox(){
global $post;
$template = get_post_meta($post->ID, '_wp_page_template', true);
echo "
<label class='screen-reader-text' for='page_template'>Page Template</label>
<select name='_wp_page_template' id='page_template'>
<option value='default'>Default Template</option>";
page_template_dropdown($template);
echo "</select>";
}
/**
* Save the page template
* @return void
*/
function save_page_template($post_id){
# Skip the auto saves
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return;
elseif ( defined( 'DOING_AJAX' ) && DOING_AJAX )
return;
elseif ( defined( 'DOING_CRON' ) && DOING_CRON )
return;
# Only update the page template meta if we are on our specific post type
elseif(MY_CUSTOM_POST_TYPE === $_POST['post_type'])
update_post_meta($post_id, '_wp_page_template', esc_attr($_POST['_wp_page_template']));
}
add_action('save_post', 'save_page_template');
/**
* Set the page template
* @param string $template The determined template from the WordPress brain
* @return string $template Full path to predefined or custom page template
*/
function set_page_template($template){
global $post;
if(MY_CUSTOM_POST_TYPE === $post->post_type){
$custom_template = get_post_meta($post->ID, '_wp_page_template', true);
if($custom_template)
#since our dropdown only gives the basename, use the locate_template() function to easily find the full path
return locate_template($custom_template);
}
return $template;
}
add_filter('single_template', 'set_page_template');
Dies ist eine etwas verspätete Antwort, aber ich dachte, es wäre wertvoll, da niemand im Web diesen Ansatz dokumentiert hat, soweit ich das beurteilen kann. Hoffe das hilft jemandem aus.
In meinem Fall sind die benutzerdefinierten Post-Typen "Album" und "Track" durch eine Album-Taxonomie verknüpft. Ich wollte in der Lage sein, abhängig von ihrer Albumtaxonomie verschiedene Einzelvorlagen für die Album- und Track-Posts zu verwenden.
Basierend auf Kaisers Antwort habe ich diesen Code geschrieben. Es läuft gut.
Hinweis. Ich habe die add_action () nicht benötigt.
// Add an additional template option to the template hierarchy
add_filter( 'single_template', 'add_albumtrack_taxslug_template', 10, 1 );
function add_albumtrack_taxslug_template( $orig_template_path )
{
// at this point, $orig_template_path is an absolute located path to the preferred single template.
$object = get_queried_object();
if ( ! (
// specify another template option only for Album and Track post types.
in_array( $object->post_type, array( 'gregory-cpt-album','gregory-cpt-track' )) &&
// check that the Album taxonomy has been registered.
taxonomy_exists( 'gregory-tax-album' ) &&
// get the Album taxonomy term for the current post.
$album_tax = wp_get_object_terms( $object->ID, 'gregory-tax-album' )
))
return $orig_template_path;
// assemble template name
// assumption: only one Album taxonomy term per post. we use the first object in the array.
$template = "single-{$object->post_type}-{$album_tax[0]->slug}.php";
$template = locate_template( $template );
return ( !empty( $template ) ? $template : $orig_template_path );
}
Ich kann jetzt Vorlagen mit den Namen single-gregory-cpt-track-tax-serendipity.php und single-gregory-cpt-album-tax-serendipity.php erstellen und WP verwendet sie automatisch. 'tax-serendipity' ist der Slug für den ersten Begriff der Album-Taxonomie.
als Referenz wird der Filter-Hook 'single_template' deklariert in:
/wp-includes/theme.php: get_query_template()
Vielen Dank Kaiser für den Beispielcode.
Prost, Gregory
Beim Update für Brians-Code stellte ich fest, dass die "Standard" -Vorlagenoption in wp_page_template gespeichert wurde, wenn das Dropdown-Feld nicht verwendet wurde, wodurch versucht wurde, eine Vorlage mit dem Namen "Standard" zu finden. Diese Änderung überprüft nur die Option "Standard" beim Speichern und löscht stattdessen das Post-Meta (nützlich, wenn Sie die Vorlagenoption wieder auf den Standard zurückgesetzt haben).
elseif (MY_CUSTOM_POST_TYPE === $ _POST ['post_type']) { if (esc_attr ($ _POST ['_wp_page_template']) ==== "default"): delete_post_meta ($ post_id, '_wp_page_template'); else: update_post_meta ($ post_id, '_wp_page_template', esc_attr ($ _POST ['_wp_page_template'); endif; }