single - {$ post_type} - {slug} .php pour les types de publication personnalisés

19

Ma partie préférée de la hiérarchie de modèles de Wordpress est la possibilité de créer rapidement des fichiers de modèle de pages pour les pages, sans devoir les modifier. la page dans Wordpress pour sélectionner un modèle.

Nous pouvons actuellement faire ceci:

  

page- {slug} .php

Mais j'aimerais pouvoir faire ceci:

  

single- {post_type} - {slug} .php

Pour que, par exemple, dans un type de message appelé review , je puisse créer un modèle pour un message intitulé "Ma grande critique" à single-review-my-great-review.php

Quelqu'un a-t-il déjà organisé cela single-{post_type}-{slug}.php

    
posée supertrue 02.02.2012 - 17:36

6 réponses

18

A) La base dans le noyau

Comme vous pouvez le voir dans dans l'explication de la hiérarchie de modèles Codex , single-{$post_type}.php est déjà pris en charge.

B) Extension de la hiérarchie principale

Maintenant, il y a volontiers des filtres et des crochets à l'intérieur de /wp-includes/template-loader.php .

  • do_action('template_redirect');
  • apply_filters( 'template_include', $template )
  • AND: un filtre spécifique à l'intérieur de get_query_template( $type, ... ) nommé: "$type}_template"

B.1) Comment ça marche

  1. Dans le fichier du chargeur de modèles, le modèle est chargé par une requête conditionnelle var / wp_query: is_*() .
  2. Le conditionnel se déclenche ensuite (dans le cas d'un modèle "unique"): is_single() && $template = get_single_template()
  3. Ceci déclenche alors get_query_template( $type, $templates ) , où $type est single
  4. Nous avons ensuite le filtre "{$type}_template"

C) La solution

Comme nous seulement voulons étendre la hiérarchie avec un modèle qui est chargé avant le modèle "single-{$object->post_type}.php" actuel, nous interceptons la hiérarchie et ajoutons 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 tout ce dont vous avez besoin dans le global (object) $post .

Billets Trac

L'approche ci-dessus n'étant actuellement pas prise en charge (vous pouvez uniquement filtrer le chemin situé de manière absolue), voici une liste des tickets de traçage:

réponse donnée kaiser 02.02.2012 - 18:25
3

Suite à la image de la hiérarchie des modèles , je ne vois pas cette option.

Alors voici comment je le ferais:

Solution 1 (le meilleur à mon avis)

Créez un fichier de 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èmes, il apparaîtrait comme une option de modèle dans la page de modification de votre message.

Solution 2

Ceci pourrait probablement être réalisé avec 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' );

MODIFIER

Ajout du file_exists check

    
réponse donnée Shane 02.02.2012 - 18:06
2

La réponse principale (depuis 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 );
?>
    
réponse donnée skladany 09.06.2016 - 22:39
1

Utiliser les modèles de page

Une autre approche en matière d’évolutivité consisterait à dupliquer la fonctionnalité de liste déroulante de modèle de page sur le type de publication page pour votre type de publication personnalisée.

Code réutilisable

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 considérablement la tâche des développeurs. Au lieu de créer un modèle pour chaque slug, vous aurez probablement besoin d'un modèle un-à-plusieurs pouvant être réutilisé au lieu d'un post-sur-modèle.

Le code

# 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 j’ai pensé 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.

    
réponse donnée Brian Fegter 13.10.2012 - 08:29
1

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.

D'après la réponse de Kaiser ci-dessus, j'ai écrit ce code. Cela fonctionne 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 utilisera automatiquement; 'tax-serendipity' est la limace du premier terme de taxonomie de l'album.

Pour référence, le crochet de filtre 'single_template' est déclaré dans:
/wp-includes/theme.php: get_query_template()

Merci Kaiser pour l'exemple de code.

Salut, Grégoire

    
réponse donnée Gregory 18.04.2012 - 08:46
0

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']) === "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;
}
    
réponse donnée Mark 29.05.2014 - 20:20

Lire d'autres questions sur les étiquettes