web-dev-qa-db-fra.com

Appliquer un modèle à un type d'article personnalisé

Aujourd'hui, j'ai eu un client qui voulait un modèle personnalisé pour chaque page et section à l'intérieur. J'ai proposé Laravel custom sh3t, mais il voulait WordPress, car il semble plus facile de passer à la main ( pas de mon expérience ).

.. Jusqu'ici tout va bien. Je suis un peu confus là-bas.

J'ai donc décidé que mon entité parente serait une page afin de pouvoir appliquer un modèle différent à chaque page. Ensuite, j'ai une section dans cette page, qui ne devrait pas être corrigée. L'utilisateur devrait avoir la possibilité de choisir la disposition des sections ( template ) et de supprimer ou de réorganiser les sections de la page en cours. Et enfin, j'ai des messages car ils sont la plus petite entité du site. Les messages seraient affichés sous forme de colonnes comme dans bootstrap ( col-md-2, col-lg-6 ), etc.

J'ai décidé de créer un type d'article personnalisé pour l'utiliser en tant que section, mais j'ai ensuite lu que les types d'article ne peuvent pas avoir de modèle, seules les pages peuvent en avoir. Cela a compromis mon plan jusqu'ici et a passé 5 heures à rechercher une solution ( pas de sortie ). J'ai donc besoin d'une autre stratégie pour le faire. J'ai besoin de modèles pour deux entités.

Quelqu'un peut-il suggérer une solution à ce problème? ( Je vais vous acheter une bière! )

MODIFIER:

Pour créer mon propre type de message personnalisé , j'utilise un plugin dans wordpress appelé 'Interface utilisateur du type de message personnalisé' , bien sûr, il existe un autre moyen de coller un extrait de code dans votre functions.php fichier, mais je ne couvre pas cela ici.

1
Dimitrov

En règle générale, je ne suivrais pas une réponse aussi forte que celle fournie par @Milo avec un message comme celui-ci. Comme j'avais déjà écrit ce code pour un autre projet, je pensais le partager.

Le code ci-dessous fait tout ce que @Milo a résumé dans sa réponse et je l'ai déjà porté avec succès sur plusieurs projets auparavant.

Voici la feuille de triche pour ce qui se passe:

1) Accrochez-vous à l'action 'add_meta_boxes' pour afficher une nouvelle boîte méta personnalisée sur l'écran d'édition (sauf sur le type de publication 'page' natif).

2) Accrochez-vous à l'action 'admin_menu' pour supprimer la méta-boîte 'Attributs de page' existante (sauf sur le type de publication 'page' natif).

3) Créez la méta-boîte personnalisée pour remplacer les fonctionnalités de la méta-boîte native "Attributs de page". Cela inclut les champs permettant de définir le PARENT, le MODÈLE et l’ORDRE de tout type de publication personnalisé que vous avez initialisé.

4) Accrochez-vous à l'action 'save_post' pour enregistrer votre sélection de modèle dans la méta-publication.

5) Accrochez-vous au filtre 'single_template' pour charger votre modèle personnalisé à la place du modèle WordPress par défaut.

Voici le copier/coller entièrement fonctionnel pour vous:

/** Custom Post Type Template Selector **/
function cpt_add_meta_boxes() {
    $post_types = get_post_types();
    foreach( $post_types as $ptype ) {
        if ( $ptype !== 'page') {
            add_meta_box( 'cpt-selector', 'Attributes', 'cpt_meta_box', $ptype, 'side', 'core' );
        }
    }
}
add_action( 'add_meta_boxes', 'cpt_add_meta_boxes' );

function cpt_remove_meta_boxes() {
    $post_types = get_post_types();
    foreach( $post_types as $ptype ) {
        if ( $ptype !== 'page') {
            remove_meta_box( 'pageparentdiv', $ptype, 'normal' );
        }
    }
}
add_action( 'admin_menu' , 'cpt_remove_meta_boxes' );

function cpt_meta_box( $post ) {
    $post_meta = get_post_meta( $post->ID );
    $templates = wp_get_theme()->get_page_templates();

    $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 ( $pages ) { 
            echo "<p><strong>Parent</strong></p>";
            echo "<label class=\"screen-reader-text\" for=\"parent_id\">Parent</label>";
            echo $pages;
        }
    }

    // Template Selector
    echo "<p><strong>Template</strong></p>";
    echo "<select id=\"cpt-selector\" name=\"_wp_page_template\"><option value=\"default\">Default Template</option>";
    foreach ( $templates as $template_filename => $template_name ) {
        if ( $post->post_type == strstr( $template_filename, '-', true) ) {
            if ( isset($post_meta['_wp_page_template'][0]) && ($post_meta['_wp_page_template'][0] == $template_filename) ) {
                echo "<option value=\"$template_filename\" selected=\"selected\">$template_name</option>";
            } else {
                echo "<option value=\"$template_filename\">$template_name</option>";
            }
        }
    }
    echo "</select>";

    // Page order
    echo "<p><strong>Order</strong></p>";
    echo "<p><label class=\"screen-reader-text\" for=\"menu_order\">Order</label><input name=\"menu_order\" type=\"text\" size=\"4\" id=\"menu_order\" value=\"". esc_attr($post->menu_order) . "\" /></p>";
}

function save_cpt_template_meta_data( $post_id ) {

    if ( isset( $_REQUEST['_wp_page_template'] ) ) {
        update_post_meta( $post_id, '_wp_page_template', $_REQUEST['_wp_page_template'] );
    }
}
add_action( 'save_post' , 'save_cpt_template_meta_data' );

function custom_single_template($template) {
    global $post;

    $post_meta = ( $post ) ? get_post_meta( $post->ID ) : null;
    if ( isset($post_meta['_wp_page_template'][0]) && ( $post_meta['_wp_page_template'][0] != 'default' ) ) {
        $template = get_template_directory() . '/' . $post_meta['_wp_page_template'][0];
    }

    return $template;
}
add_filter( 'single_template', 'custom_single_template' );
/** END Custom Post Type Template Selector **/

La seule hypothèse que j'ai faite ici est que vos modèles sont conformes aux meilleures pratiques de convention de dénomination suivantes:

posttype-templatename.php

A titre d'exemple, vous pouvez définir des modèles personnalisés pour un type de publication personnalisé "Event" à l'aide de la convention de dénomination suivante dans votre thème:

event-standard.php
event-allday.php
event-recurring.php

Ce code est suffisamment intelligent pour autoriser uniquement les modèles "d'événement" à être appliqués au type de publication d'événement. En d'autres termes, un modèle appelé modèle "section-video.php" ne serait jamais visible pour le type de publication d'événement. Ce modèle apparaîtrait plutôt comme une option sur le type d'article "Section".

Pour supprimer cette fonctionnalité, il vous suffit de supprimer la logique conditionnelle du code ci-dessus:

if ( $post->post_type == strstr( $template_filename, '-', true) ) {  }
5
dswebsme

Depuis WordPress 4.7, plusieurs types de publication ont été pris en charge par plusieurs modèles.

Afin de rendre un modèle disponible pour votre type de publication personnalisée, vous ajoutez cet en-tête à la partie méta du fichier de modèle:

Template Post Type: post, foo, bar 

Par exemple, nous supposerons que votre type de publication personnalisée est intitulé "my_events" et que vous souhaitez créer un modèle appelé "Largeur totale" disponible pour les deux pages et votre type de publication personnalisée.

This:

/**
 * Template Name: Fullwidth
 * 
 * Template Description...
 **/

devient ceci:

/**
 * Template Name: Fullwidth
 * Template Post Type: page, my_events
 * 
 * Template Description...
 **/

Plus d'infos: Modèles de type de message dans 4.7 à partir de WordPress Core

13
Landing on Jupiter

Les types de publication personnalisés peuvent avoir des modèles sélectionnables, vous devrez simplement les implémenter vous-même. WordPress le fait en interne avec le type de publication de page en enregistrant un slug de modèle dans les métadonnées de publication, puis en vérifiant si une valeur existe lorsque le modèle est chargé sur le front-end conformément à la hiérarchie .

Le processus de base consisterait à ajouter une méta-boîte à votre type de message personnalisé pour permettre aux utilisateurs de sélectionner un modèle (éventuellement avec get_page_templates pour créer une liste).

La deuxième étape consiste à ajouter un filtre à single_template pour charger le modèle sélectionné lorsque cet objet est visualisé dans le frontal.

Si vous regardez à l'intérieur des fichiers de base wp-includes/template.php et wp-includes/post-template.php, vous pouvez voir le code utilisé par WordPress (et l'endroit où le filtre est appliqué) et l'adapter à vos besoins. get_queried_object vous donnera le post_type de l'objet dans le filtre, ainsi que l'ID permettant de récupérer les métadonnées de l'article.

MODIFIER -

Voici un exemple de filtre pour le type de message post qui charge tout ce qui se trouve dans la clé méta my_template (comme whatever.php). Vous pouvez le tester en créant une nouvelle publication et en entrant un nom de fichier sous cette clé à l'aide de la boîte à méta Native Fields. Vous pouvez le modifier pour votre type personnalisé (change 'post') et pour tout modèle que vous utilisez pour stocker et nommer des fichiers.

function wpd_post_type_template( $template ){
    $object = get_queried_object();
    if( ! empty( $object->post_type )
        && 'post' == $object->post_type
        && $slug = get_post_meta( $object->ID, 'my_template', true ) ){
        if( $custom_template = locate_template( $slug, false ) ){
            $template = $custom_template;
        }
    }
    return $template;
}
add_filter( 'single_template', 'wpd_post_type_template' ) ;
1
Milo