カスタム投稿タイプがいくつか登録されています。各カスタム投稿タイプのすべての「投稿」を独自のページに表示したいのですが、これらのページはナビゲーションメニューに表示されている必要があります。
各カスタム投稿タイプのページテンプレートに関して、page-custom.php
テンプレートが1つだけあるのは素晴らしいことです。このようなものを作ることは可能ですか?
元のコードには多くの問題がありました
重大なセキュリティ問題につながる可能性があるデータがサニタイズおよび検証されていない
いくつかの部分は繰り返しました
少し面倒で読みにくい
一部のセクションは部分的にしか機能していませんでした
本当に邪悪な中古グローバル
上記の問題を解決するために私がこの回答を再検討し、コードを更新したのはそのためです。コードは、よりクリーンで、より安全で、そして読みやすくそしてデバッグしやすくなりました。必ずORIGINAL ANSWERセクションでチェックしてください。
元のORIGINAL ANSWERセクションに進む前に、もう少し使いやすいと思う代替手段を追加したいと思います。
これは、カスタムテンプレート(content.php
を除く)やテンプレートの変更を伴わない直接的な代替ソリューションです。あなたがする必要があるのはただ
あなたが望む任意のページテンプレートで新しいページを作成する
あなたのテーマがデフォルトでこれらを利用できない場合、そのようなテンプレートパーツのcontent.php
テンプレートパーツを作成します
次のコードを追加すれば完了です。
$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();
PreGetPostsForPages
クラスは ここに私の答えで そしてそれを使用する方法に関する詳細な説明もあります。
テンプレート階層 を見ると、カスタム投稿タイプは通常アーカイブテンプレートに表示されます。通常のテンプレート階層では、デフォルトでカスタム投稿タイプを表示するために使用されるpage.php
タイプのテンプレートは用意されていません。
アーカイブテンプレートの問題は、デフォルトのナビゲーションメニューに自動的に追加されないことです。また、リンクを作成するためのカスタムメニューを作成することが、必ずしも最も便利な方法とは限りません。
ここへ行く方法は WP_Query
を使ってカスタム投稿タイプを含めるためのループのためのカスタムクエリを作成することです。 WP_Query
には、 post types を呼び出すために使用されるpost_type
typeパラメータがあります。
したがって、これを機能させるには、以下を変更する必要があります。
まず、カスタムのpage.php
テンプレートを作成します
カスタムのpage.php
を作成するには、テーマのpage.php
をコピーしてpage-cpt.php
のような名前に変更する必要があります。それを開き、ループを変更してください。この答えのために、私はデフォルトの14のテーマを使いました。テンプレート内のすべてのものを削除して、このコードに置き換えます
EDITコードを変更するために戻ってきました。前のコードでは、カスタムクエリで次のコードを使用していました。
global $post;
$tmp_post = $post;
$wp_query= null;
$wp_query = new WP_Query();
$wp_query->query( $args );
これはquery_posts
にも変換されますが、決して使用しないでください。そのため、WP_Query
の適切なインスタンスを実行するようにコードを変更します。これが編集したコードです。
<?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();
最初のコードは、dbから設定を呼び出すために使用されます。これは、ページエディタ画面で新しいページを作成するときにバックエンドのメタボックスを介して設定されます。ここで重要なコードはWP_Query
の引数です。
$args = [
'post_type' => $posttype,
'posts_per_page' => $post_count,
'paged' => $paged,
'order' => $asc,
'ignore_sticky_posts' => 1,
];
これにより、どのカスタム投稿タイプが表示されるか、ページごとの投稿数、および投稿の順序が決まります。これらの設定はすべてdbから呼び出され、バックエンドのカスタムメタボックスに設定されます。
次に、 カスタムメタボックスを作成します
このメタボックスは、新しいページが作成され、[ページ属性]メタボックスで[カスタム投稿タイプページ]が選択されたときに[ページ]画面に表示されます。
functions.php
またはカスタム関数ファイルに以下を追加します。
<?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 );
}
}
このコードがすることは、メタボックスを登録して表示し、メタボックスにオプションを追加し、page-cpt.php
テンプレートで使用するためにオプションをdbに格納することです。
これで移動して新しいページを作成し、そのページを好きなように呼び出すことができます。 [ページ属性]で、[カスタム投稿タイプページ]と[公開]ページを選択します。カスタム投稿タイプオプションのメタボックスは、「公開」メタボックスの上に表示され、現在利用可能なすべてのカスタム投稿タイプが表示されます。表示する必要があるオプションを選択して設定し、[更新]をクリックします。あなたのページはあなたが選択したカスタム投稿タイプからの投稿を表示し、あなたのページはナビゲーションバーに表示されます。
これにさらに機能を追加することも、同じ方法でカテゴリまたは分類法を表示するようにコードを変更することもできます。この助けを願っています