Ma partie préférée de la hiérarchie de Wordpress template est la possibilité de créer rapidement des fichiers de gabarit pour les pages par slug, sans avoir à modifier la page dans Wordpress pour sélectionner un gabarit.
Nous pouvons actuellement faire ceci:
page- {slug} .php
Mais j'aimerais pouvoir faire ceci:
single- {post_type} - {slug} .php
Ainsi, par exemple, dans un type de message appelé review
, je pourrais créer un modèle pour un message appelé "My Great Review" à single-review-my-great-review.php
Quelqu'un a-t-il déjà organisé cela? single-{post_type}-{slug}.php
Comme vous pouvez le voir dans l'explication Codex Template Hierarchy, single-{$post_type}.php
est déjà pris en charge.
Maintenant, il y a volontiers des filtres et des crochets dans /wp-includes/template-loader.php
.
do_action('template_redirect');
apply_filters( 'template_include', $template )
get_query_template( $type, ... )
nommé: "$type}_template"
is_*()
.is_single() && $template = get_single_template()
get_query_template( $type, $templates )
, où $type
est single
"{$type}_template"
Comme nous seulement voulons étendre la hiérarchie avec un modèle qui obtient chargé avant le modèle "single-{$object->post_type}.php"
actuel, nous intercepterons la hiérarchie et ajouterons un nouveau modèle au début du tableau de modèles. .
// 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 );
NOTE: (Si vous voulez utiliser autre chose que le slug des objets par défaut), vous devrez ajuster $slug
en fonction de votre structure de lien permanent. Utilisez simplement ce dont vous avez besoin dans le (object) $post
global.
Comme l'approche ci-dessus est actuellement not supportée (vous pouvez uniquement filtrer le chemin absolu de cette façon), voici une liste des tickets de traçage:
Suivant l’image Template Hierarchy , je ne vois pas une telle option.
Alors voici comment je le ferais:
Solution 1 (Best à mon avis)
Créez un fichier modèle et associez-le à la révision
<?php
/*
Template Name: My Great Review
*/
?>
En ajoutant le modèle de fichier php dans votre répertoire de thème, il apparaîtrait comme une option de modèle dans la page d'édition de votre publication.
Solution 2
Ceci pourrait probablement être réalisé en utilisant template_redirect
hook.
Dans le fichier functions.php:
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
Ajout du contrôle file_exists
La meilleure réponse (d'il y a 4 ans) ne fonctionne plus, mais le codex WordPress a la solution ici :
<?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 );
?>
Une autre approche en matière d'évolutivité consisterait à dupliquer la fonctionnalité de liste déroulante de modèle de page sur le type d'article page
pour votre type d'article personnalisé.
La duplication dans le code n'est pas une bonne pratique. Les heures supplémentaires peuvent causer de graves problèmes de saturation à une base de code, ce qui complique la gestion du développeur. Au lieu de créer un modèle pour chaque slug, vous aurez probablement besoin d'un modèle un-à-plusieurs qui peut être réutilisé au lieu d'un modèle un à un.
# 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');
C'est une réponse un peu tardive, mais je pensais que ce serait utile, car personne sur le Web n'a documenté cette approche à ce que je sache. J'espère que cela aide quelqu'un.
Dans mon cas, les types de publication personnalisés Album et Suivi sont liés par une taxonomie d’Album. Je souhaitais pouvoir utiliser différents modèles Single pour les publications Album et Track en fonction de leur taxonomie.
Basé sur la réponse de Kaiser ci-dessus, j'ai écrit ce code. Ça marche bien.
Remarque. Je n'ai pas eu besoin de add_action ().
// 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 );
}
Je peux maintenant créer des modèles nommés single-gregory-cpt-track-tax-serendipity.php et single-gregory-cpt-album-tax-serendipity.php et WP les utiliseront automatiquement; 'tax-serendipity' est la limace du premier terme de taxonomie de l'album.
pour référence, le hook de filtre 'single_template' est déclaré dans:
/wp-includes/theme.php: get_query_template()
Merci Kaiser pour l'exemple de code.
À la vôtre, Gregory
Mise à jour pour le code Brians, j'ai constaté que lorsque le menu déroulant n'était pas utilisé, l'option de modèle "par défaut" était en cours d'enregistrement dans wp_page_template, ce qui l'avait amené à rechercher un modèle appelé par défaut. cette modification vérifie simplement l'option "par défaut" lors de l'enregistrement et supprime la méta de publication (utile si vous avez modifié l'option de modèle à sa valeur par défaut)
elseif (MY_CUSTOM_POST_TYPE === $ _POST ['post_type']) { if (esc_attr ($ _ POST ['_ wp_page_template'])) === "défaut"): delete_post_meta ($ post_id, '_wp_page_template'); else: update_post_meta ($ post_id, '_wp_page_template', esc_attr ($ _ POST ['_ wp_page_template')), fin si; }