J'ai quelques types de messages personnalisés enregistrés. J'aimerais afficher tous les "articles" de chaque type d'article personnalisé sur sa propre page. Ces pages doivent être visibles dans le menu de navigation.
Ce serait bien de n'avoir qu'un seul modèle page-custom.php
pour un modèle de page pour chaque type de publication personnalisée. Est-il possible de créer quelque chose comme ça?
Le code original avait de nombreux problèmes
Les données n'ont pas été désinfectées et validées, ce qui peut entraîner de graves problèmes de sécurité
Certaines parties étaient répétitives
Un peu brouillon et parfois difficile à lire
Certaines sections ne fonctionnaient que partiellement
Globals utilisés qui est vraiment diabolique
C'est pourquoi j'ai revisité cette réponse et mis à jour le code afin de résoudre les problèmes ci-dessus. Le code est maintenant plus propre, plus sûr et plus facile à lire et à déboguer. Assurez-vous de le vérifier dans la section ORIGINAL REPONSE
Avant de passer à la section originale ORIGINAL REPONSE , je souhaite ajouter une alternative qui, à mon avis, est un peu préférable.
Il s’agit d’une solution alternative simple qui n’implique pas de modèles personnalisés (, sauf peut-être un content.php
) ni la modification de modèles. Tout ce que vous devez faire c'est
créer une nouvelle page avec le modèle de page de votre choix
créer une partie de modèle content.php
dans l'une de ces parties si votre thème ne les a pas disponibles par défaut
ajoutez le code suivant et votre fait
$query = new PreGetPostsForPages(
251, // Page ID we will target
'content', //Template part which will be used to display posts, name should be without .php extension
true, // Should get_template_part support post formats
false, // Should the page object be excluded from the loop
[ // Array of valid arguments that will be passed to WP_Query/pre_get_posts
'post_type' => 'post',
'posts_per_page' => 2
]
);
$query->init();
La classe PreGetPostsForPages
peut être trouvée dans ma réponse ici et une explication détaillée sur la façon de l'utiliser
Si vous examinez la hiérarchie des modèles , les types d'articles personnalisés sont généralement affichés dans les modèles d'archives. La hiérarchie normale des modèles ne prévoit pas que les modèles de type page.php
soient utilisés pour afficher les types de publication personnalisés par défaut.
Le problème avec les modèles d'archive est qu'ils ne sont pas automatiquement ajoutés au menu de navigation par défaut et la création d'un menu personnalisé pour créer des liens n'est pas toujours le moyen le plus pratique.
Pour y parvenir, utilisez WP_Query
pour créer une requête personnalisée pour la boucle afin d'inclure les types de publication personnalisés. WP_Query
possède un paramètre de type post_type
qui est utilisé pour appeler les types de publication .
Il faut donc modifier les éléments suivants pour que cela fonctionne:
Tout d'abord, créez un modèle personnalisé page.php
Pour créer le page.php
personnalisé, vous devez copier le page.php
de votre thème et le renommer en quelque chose comme page-cpt.php
. Maintenant, ouvrez-le et changez la boucle. Pour répondre à cette question, j'ai utilisé le thème par défaut vingt-quatre. Supprimer tout le contenu du modèle et le remplacer par ce code
EDIT Je suis revenu pour changer le code. Le code précédent utilisait les éléments suivants dans la requête personnalisée
global $post;
$tmp_post = $post;
$wp_query= null;
$wp_query = new WP_Query();
$wp_query->query( $args );
qui se traduisent également par query_posts
, qui ne devrait jamais être utilisé. Donc, je modifie le code en conséquence pour exécuter une instance appropriée de WP_Query
. Voici le code édité
<?php
/**
* Template Name: Custom Post Type Page
*/
get_header(); ?>
<?php
//See if we have any values
$post_meta = get_post_meta( $post->ID,false );
$posttype = isset( $post_meta['_cpt_post_type'] ) ? $post_meta['_cpt_post_type'][0] : 1;
$page_title = isset( $post_meta['_cpt_page_title'] ) ? $post_meta['_cpt_page_title'][0] : '';
$posts_title = isset( $post_meta['_cpt_posts_title'] ) ? $post_meta['_cpt_posts_title'][0] : '';
$orderby = isset( $post_meta['_cpt_order_by'] ) ? $post_meta['_cpt_order_by'][0] : 'date';
$asc = isset( $post_meta['_cpt_asc'] ) ? $post_meta['_cpt_asc'][0] : 'DESC';
$post_count = isset( $post_meta['_cpt_post_count'] ) ? $post_meta['_cpt_post_count'][0] : get_option('posts_per_page');
?>
<div id="main-content" class="main-content">
<div id="primary" class="content-area">
<div id="content" class="site-content" role="main">
<!-- Page Title -->
<?php if( $page_title ) { ?>
<article id="posts-title">
<header class="entry-header">
<h2 class="entry-title"><?php echo $page_title; ?></h2>
</header><!-- .entry-header -->
</article><!-- #posts-title -->
<?php } ?>
<?php the_post(); ?>
<?php global $post;
if( $post->post_content || $page_title ) : ?>
<div class="entry-content">
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<?php if( $posts_title ) : ?>
<header class="entry-header">
<h1 class="entry-title"><?php echo $posts_title; ?></h1>
</header><!-- .entry-header -->
<?php endif; ?>
<?php if( $post->post_content ) : ?>
<div class="entry-content">
<?php the_content(); ?>
<?php wp_link_pages( ['before' => '<div class="page-link"><span>' . __( 'Pages:' ) . '</span>', 'after' => '</div>'] ); ?>
</div><!-- .entry-content -->
<footer class="entry-meta">
</footer><!-- .entry-meta -->
<?php endif; ?>
</article><!-- #post-<?php the_ID(); ?> -->
</div>
<?php endif; ?>
<?php
/**-----------------------------------------------------------------------------
*
* Start our custom query to display custom post type posts
*
*------------------------------------------------------------------------------*/
$args = [
'post_type' => $posttype,
'posts_per_page' => $post_count,
'paged' => $paged,
'order' => $asc,
'ignore_sticky_posts' => 1,
];
$cpt_query = new WP_Query($args);
// Output
if ( $cpt_query->have_posts() ) :
// Start the Loop.
while ( $cpt_query->have_posts() ) {
$cpt_query->the_post();
get_template_part( 'content', get_post_format() );
}
if ( function_exists( 'pietergoosen_pagination' ) )
pietergoosen_pagination();
wp_reset_postdata();
} else {
get_template_part( 'content', 'none' );
} ?>
</div><!-- #content -->
</div><!-- #primary -->
<?php get_sidebar( 'content' ); ?>
</div><!-- #main-content -->
<?php
get_footer();
Le premier morceau de code est utilisé pour appeler les paramètres de la base de données. Ceci sera défini via une metabox dans le back-end lors de la création d'une nouvelle page dans l'écran de l'éditeur de page. Le code important ici est constitué par les arguments de WP_Query
.
$args = [
'post_type' => $posttype,
'posts_per_page' => $post_count,
'paged' => $paged,
'order' => $asc,
'ignore_sticky_posts' => 1,
];
Cela décidera quels types de messages personnalisés seront affichés, messages par page et l'ordre des messages. Tous ces paramètres sont appelés à partir de la base de données et sont définis dans la boîte méta personnalisée du back-end
Deuxièmement, créez une méta-boîte personnalisée
Cette métabox sera affichée dans l'écran "Page" lorsqu'une nouvelle page est créée et que "Page de type de publication personnalisée" est sélectionné dans la boîte à méta "Attributs de page".
Ajoutez les éléments suivants dans votre fichier functions.php
ou dans le fichier de fonctions personnalisées
<?php
add_action( 'admin_init', function ()
{
$post_id = filter_input( INPUT_GET, 'post', FILTER_VALIDATE_INT );
if ( $post_id ) {
// Get the current page template
$post_meta = get_post_meta( $post_id );
// Make sure that we only target our desired template
if ( isset ( $post_meta['_wp_page_template'][0] )
&& 'page-cpt.php' === $post_meta['_wp_page_template'][0]
) {
add_meta_box(
'cpt_meta_box',
__( 'Page of post from a given custom post type' ),
'cpt_metabox_options',
'page',
'side',
'core'
);
} else {
if( isset( $meta['_cpt_post_type'][0] ) ) {
$meta_value_array = [
'_cpt_post_type',
'_cpt_page_title',
'_cpt_posts_title',
'_cpt_order_by',
'_cpt_asc',
'_cpt_post_count'
];
foreach ( $meta_value_array as $value )
cpt_helper_update_post_meta( $post_id, $value, '' );
remove_meta_box( 'cpt_meta_box', 'page', 'side' );
}
}
}
add_action( 'save_post', 'cpt_update_post_meta_box' );
});
function get_cpt_order_by_list()
{
// Set the sort order
$sort = [
[
'DESC' => [
'value' => 'DESC',
'label' => 'Descending'
],
'ASC' => [
'value' => 'ASC',
'label' => 'Ascending'
],
]
];
// Create an array of values to order the posts by
$order_list = [
[
'none' => [
'value' => 'none',
'label' => 'None'
],
'id' => [
'value' => 'ID',
'label' => 'Post ID'
],
'author' => [
'value' => 'author',
'label' => 'Author'
],
'title' => [
'value' => 'title',
'label' => 'Post Title'
],
'date' => [
'value' => 'date',
'label' => 'Post Date'
],
'modified' => [
'value' => 'modified',
'label' => 'Modified Date'
],
'parent' => [
'value' => 'parent',
'label' => 'Parent Post'
],
'Rand' => [
'value' => 'Rand',
'label' => 'Random'
],
'comment_count' => [
'value' => 'comment_count',
'label' => 'Comment Count'
],
'menu_order' => [
'value' => 'menu_order',
'label' => 'Menu Order'
],
]
];
return $list = array_merge( $sort, $order_list );
}
function cpt_metabox_options()
{
$post_id = filter_input( INPUT_GET, 'post', FILTER_VALIDATE_INT );
if ( !$post_id )
return;
// Make sure the current user have the edit_page ability
if ( !current_user_can( 'edit_post', $post_id ) )
return;
// Get the current page template
$template_file = get_post_meta( $post_id, '_wp_page_template', true );
// Make sure that we only target our desired template
if ( 'page-cpt.php' !== $template_file )
return;
// Get all the post meta values and sanitize/validate them
$post_meta = get_post_meta( $post_id );
$filters = [
'_cpt_post_type' => [
'filter' => FILTER_SANITIZE_STRING,
'default' => ''
],
'_cpt_page_title' => [
'filter' => FILTER_SANITIZE_STRING,
'default' => ''
],
'_cpt_posts_title' => [
'filter' => FILTER_SANITIZE_STRING,
'default' => ''
],
'_cpt_order_by' => [
'filter' => FILTER_SANITIZE_STRING,
'default' => 'ID'
],
'_cpt_asc' => [
'filter' => FILTER_SANITIZE_STRING,
'default' => 'DESC'
],
'_cpt_post_count' => [
'filter' => FILTER_VALIDATE_INT,
'default' => get_option( 'posts_per_page' )
],
];
foreach ( $filters as $key=>$value ) {
if ( !array_key_exists( $key, $post_meta ) ) {
$post_meta[$key][0] = $value['default'];
} else {
$post_meta[$key][0] = filter_var( $post_meta[$key][0], $value['filter'], $value['default'] );
}
}
?>
<!-- Sart the meta boxes -->
<div class="inside">
<p>
<label>
<strong><?php _e( 'Page Title' ); ?></strong>
</label>
</p>
<input id="_cpt_page_title" name="_cpt_page_title" type="text" style="width: 98%;" value="<?php echo $post_meta['_cpt_page_title'][0]; ?>"/>
<p>
<label>
<strong><?php _e( 'Post Title' ); ?></strong>
</label>
</p>
<input id="_cpt_posts_title" name="_cpt_posts_title" type="text" style="width: 98%;" value="<?php echo $post_meta['_cpt_posts_title'][0]; ?>"/>
<p>
<label>
<strong><?php _e( 'Custom Post Type' ); ?></strong>
</label>
</p>
<select id="_cpt_post_type" name="_cpt_post_type">
<?php
//Custom Post Type List
$args = [
'public' => true,
'_builtin' => false
];
$output = 'names'; // names or objects, note names is the default
$operator = 'and'; // 'and' or 'or'
$post_types = get_post_types( $args, $output, $operator );
foreach ( $post_types as $post_type ) {
$selected = ( $post_type == $post_meta['_cpt_post_type'][0] ) ? ' selected = "selected" ' : '';
$option = '<option '.$selected .'value="'. $post_type;
$option = $option .'">';
$option = $option .$post_type;
$option = $option .'</option>';
echo $option;
} //endforeach;
?>
</select>
<?php
if ( function_exists( 'get_pop_order_by_list' ) ) {
$list = get_pop_order_by_list();
?>
<p>
<label>
<strong><?php _e( 'Sort by' )?></strong>
</label>
</p>
<select id="_cpt_order_by" name="_cpt_order_by">
<?php
foreach ( $list[0] as $output ) {
$selected = ( $output['value'] == $post_meta['_cpt_order_by'][0] ) ? ' selected = "selected" ' : '';
$option = '<option '.$selected .'value="' . $output['value'];
$option = $option .'">';
$option = $option .$output['label'];
$option = $option .'</option>';
echo $option;
} //endforeach;
?>
</select>
<p>
<label>
<strong><?php _e( 'Order' )?><strong>
</label>
</p>
<select id="_cpt_asc" name="_cpt_asc">
<?php
foreach ( $list[1] as $output ) {
$selected = ( $output['value'] == $post_meta['_cpt_asc'][0] ) ? ' selected = "selected" ' : '';
$option = '<option '.$selected .'value="' . $output['value'];
$option = $option .'">';
$option = $option .$output['label'];
$option = $option .'</option>';
echo $option;
} //endforeach;
?>
</select>
<?php
}
?>
<p>
<label>
<strong><?php _e( 'Posts per Page' ); ?><strong>
</label>
</p>
<input id="_cpt_post_count" name="_cpt_post_count" type="text" value="<?php echo $post_meta['_cpt_post_count'][0]; ?>" size="3" />
</div>
<!-- End page of posts meta box -->
<?php
}
function cpt_update_post_meta_box( $post_id )
{
// Make sure we have a valid $_POST method
if ( !$_POST )
return;
// Make sure the current user have the edit_page ability
if ( !current_user_can( 'edit_page', $post_id ) )
return;
// Get the current page template
$template_file = get_post_meta( $post_id, '_wp_page_template', true );
// Make sure that we only target our desired template
if ( 'page-cpt.php' !== $template_file )
return;
// Do nothing on auto save, just bail
if ( defined( 'DOING_AUTOSAVE' )
&& DOING_AUTOSAVE
)
return;
$args = [
'_cpt_post_type' => [
'filter' => FILTER_SANITIZE_STRING,
'default' => ''
],
'_cpt_page_title' => [
'filter' => FILTER_SANITIZE_STRING,
'default' => ''
],
'_cpt_posts_title' => [
'filter' => FILTER_SANITIZE_STRING,
'default' => ''
],
'_cpt_order_by' => [
'filter' => FILTER_SANITIZE_STRING,
'default' => 'date'
],
'_cpt_asc' => [
'filter' => FILTER_SANITIZE_STRING,
'default' => 'DESC'
],
'_cpt_post_count' => [
'filter' => FILTER_VALIDATE_INT,
'default' => get_option( 'posts_per_page' )
],
];
$meta = filter_input_array( INPUT_POST, $args );
if ( !$meta )
return;
// Loop throught the array and update meta values
foreach ( $meta as $k=>$v )
cpt_helper_update_post_meta( $post_id, $k, $v );
}
function cpt_helper_update_post_meta( $post_id = '', $key = '', $data = '' )
{
// Make sure we have valid values, if not, return false
if ( !$post_id
|| !$key
)
return false;
// Sanitize and validate values
$post_id = filter_var( $post_id, FILTER_VALIDATE_INT );
$key = filter_var( $key, FILTER_SANITIZE_STRING );
$data = filter_var( $data, FILTER_SANITIZE_STRING );
// Get the post meta values
$post_meta = get_post_meta( $post_id, $key, true );
if( $data
&& $post_meta != $data
) {
update_post_meta( $post_id, $key, $data );
}
if ( $post_meta
&& !$data
) {
delete_post_meta( $post_id, $key );
}
}
Le but de ce code est d’enregistrer et d’afficher la boîte de métadonnées, d’ajouter les options à la métabox et de les stocker dans la base de données à utiliser dans le modèle page-cpt.php
.
Vous pouvez maintenant créer une nouvelle page et appeler la page comme vous le souhaitez. Dans les "Attributs de page", sélectionnez "Page Type de publication personnalisée" et "Publier" votre page. La métabox pour les options de types de publication personnalisée apparaîtra maintenant au-dessus de la métabox "Publier" et affichera tous les types de publication personnalisés disponibles. Sélectionnez et définissez les options à afficher, puis cliquez sur "Mettre à jour". Votre page affichera maintenant les messages du type de message personnalisé que vous avez sélectionné et votre page sera visible dans la barre de navigation.
Vous pouvez ajouter plus de fonctionnalités à cela ou changer le code pour afficher les catégories ou les taxonomies de la même manière. J'espère que cette aide