web-dev-qa-db-fra.com

Affecter un modèle de page dans un type de publication personnalisé

J'ai enregistré un type de message personnalisé et créé un fichier appelé archive-myCPT.php et un autre pour les messages simples appelé single-myCPT.php .

Ce que je veux faire, c'est créer une page sur laquelle je ne montrerai que quelques articles de mon type d'article personnalisé. Dans mon archive-myCPT.php , je vais avoir un lien appelé, disons "Messages spéciaux" et ce lien ira à la page personnalisée qui sera un peu différente de archive-myCPT.php, la seule différence est que je vais utiliser ici une requête personnalisée pour les publications.

La seule façon de faire cela semble créer un modèle de page, mais le problème ici est que je ne peux pas affecter un modèle de page aux pages de mon CPT. J'ai trouvé ce plugin qui peut m'aider à prendre en charge le modèle de page pour mon type de message personnalisé, mais il est assez ancien et je ne sais pas s'il est compatible. avec la dernière version de WordPress.

Y a-t-il un autre moyen d'y parvenir?

Est-ce une pratique courante/bonne?

Peut-être que vous pourriez recommander quelque chose d'autre?

1
agis

Si vous ajoutez une requête personnalisée dans le modèle pour charger des publications, le type de publication de cette page ne doit pas nécessairement être votre type de publication personnalisé. Vous pouvez créer une page vanille simple, créer un modèle à cet effet via page-your_page_slug.php ou via un modèle personnalisé attribué dans le menu déroulant des modèles, puis rechercher le type de publication que vous souhaitez via WP_Query.

EDIT - voici un exemple utilisant le filtre single_template. vous devrez changer le type de message et slug pour correspondre au vôtre.

function wpa_single_cpt_template( $templates = '' ){
    $single = get_queried_object();

    if( 'myCPT' == $single->post_type
        && 'my-special-slug' == $single->post_name )
        $templates = locate_template( 'my-special-template.php', false );

    return $templates;
}
add_filter( 'single_template', 'wpa_single_cpt_template' );

adapté de l'exemple sur Hiérarchie des modèles: Hiérarchie des filtres .

1
Milo

On pourrait penser que ce serait aussi simple que d’ajouter add_post_type_support( 'cptslug', 'page-attributes' ); à votre code, mais ce n’est pas le cas. Si vous cochez la source , vous verrez que la liste déroulante des modèles est limitée au type de publication page. Il y a également une note dans le Codex et une référence à un ticket Trac fermé sur le sujet.

Vous pouvez ajouter cette boîte à votre CPT en copiant la fonction principale, en effectuant une petite modification et en ajoutant une nouvelle boîte.

function my_cpt_attributes_meta_box($post) {
    $post_type_object = get_post_type_object($post->post_type);
    if ( $post_type_object->hierarchical ) {
        $dropdown_args = array(
            'post_type'        => $post->post_type,
            'exclude_tree'     => $post->ID,
            'selected'         => $post->post_parent,
            'name'             => 'parent_id',
            'show_option_none' => __('(no parent)'),
            'sort_column'      => 'menu_order, post_title',
            'echo'             => 0,
        );

        $dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post );
        $pages = wp_dropdown_pages( $dropdown_args );
        if ( ! empty($pages) ) {
?>
<p><strong><?php _e('Parent') ?></strong></p>
<label class="screen-reader-text" for="parent_id"><?php _e('Parent') ?></label>
<?php echo $pages; ?>
<?php
        } // end empty pages check
    } // end hierarchical check.

        $template = get_post_meta($post->ID,'_wp_page_template',true);

        ?>
<p><strong><?php _e('Template') ?></strong></p>
<label class="screen-reader-text" for="page_template"><?php _e('Page Template') ?></label><select name="page_template" id="page_template">
<option value='default'><?php _e('Default Template'); ?></option>
<?php page_template_dropdown($template); ?>
</select>

<p><strong><?php _e('Order') ?></strong></p>
<p><label class="screen-reader-text" for="menu_order"><?php _e('Order') ?></label><input name="menu_order" type="text" size="4" id="menu_order" value="<?php echo esc_attr($post->menu_order) ?>" /></p>
<p><?php if ( 'page' == $post->post_type ) _e( 'Need help? Use the Help tab in the upper right of your screen.' ); ?></p>
<?php
}
function add_my_cpt_attributes_meta_box() {
  add_meta_box(
    'my_cpt_attributes_meta_box',
    'My Box Name',
    'my_cpt_attributes_meta_box',
    'book',
    'side',
    'core'
  );
}
add_action( 'add_meta_boxes', 'add_my_cpt_attributes_meta_box' );

Si vous testez ce code, vous remarquerez que la boîte apparaît mais que les données ne sont pas enregistrées. Voici pourquoi .

Nous allons devoir sauvegarder les données nous-mêmes.

function my_save_cpt_template($post_ID,$post) {
  $page_template = (isset($_POST['page_template'])) ? $_POST['page_template'] : false;
  $page_templates = wp_get_theme()->get_page_templates();
//   var_dump($page_template,$page_templates,'default' != $page_template && ! isset( $page_templates[ $page_template ] )); die;
  if ( 'default' != $page_template && ! isset( $page_templates[ $page_template ] ) ) {
      if ( $wp_error )
          return new WP_Error('invalid_page_template', __('The page template is invalid.'));
      else
          return 0;
  }
  update_post_meta($post_ID, '_wp_page_template',  $page_template);
}
add_action('save_post_cptslug','my_save_cpt_template',1,2);

Maintenant, il devrait enregistrer, mais le modèle ne se charge pas. Voici pourquoi.get_single_template s'exécute avant le get_page_template, et get_page_template correspond à ce qui est recherché pour les modèles spécialisés. Nous devons donc charger ce modèle nous-mêmes.

add_action(
  'template_include',
  function ($template) {
    global $post;
    if (is_singular() && isset($post->post_type) && 'book' === $post->post_type) {
      $new = get_post_meta($post->ID,'_wp_page_template',true);
      $new = locate_template($new);
      if (!empty($new)) {
        $template = $new;
      }
    }
    return $template;
  }
);

À peine testé. Peut-être un buggy. Caveat emptor. Pas de remboursement.

1
s_ha_dum