回访:2016年2月2日,原始代码有许多问题
未对数据进行清理和验证,这可能导致严重的安全问题
有些部分是重复的
有点凌乱,有时难以阅读
一些部门只起到了部分作用
使用globals真的很邪恶
这就是为什么我重新审视这个答案并更新代码以解决上述问题的原因。代码现在更干净、更安全、更易于阅读和调试。确保在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
可以找到类
in my answer here 以及如何使用它的详细说明
原始答案,如果您查看template hierarchy, 自定义帖子类型通常显示在存档模板上。普通模板层次结构不提供page.php
默认情况下,用于显示自定义帖子类型的类型模板。
存档模板的问题是,它们不会自动添加到默认的导航菜单中,创建自定义菜单来创建链接并不总是最方便的方式。
这里的方法是使用WP_Query
为循环创建自定义查询以包括自定义帖子类型。WP_Query
祝你好运post_type
用于调用的类型参数post types.
因此,需要对以下内容进行修改以实现此目的:
首先,创建自定义page.php
样板
创建自定义page.php
你需要复制你的主题page.php
并将其重命名为page-cpt.php
. 现在打开它并更改循环。为了回答这个问题,我使用了默认的214主题。删除模板中的所有内容,并将其替换为以下代码
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调用的,并在后端的自定义元框中进行设置
其次,创建custom meta box
创建新页面并在“页面属性”元框中选择“自定义帖子类型页面”时,此元框将显示在“页面”屏幕中。
将以下内容添加到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 );
}
}
这段代码所做的是注册和显示元框,将选项添加到元框中,并将选项存储到db中,以便在page-cpt.php
样板
现在,您可以创建一个新页面,并根据需要调用该页面。在“页面属性”中,选择“自定义帖子类型页面”和“发布”页面。自定义帖子类型选项的元框现在将显示在“发布”元框的上方,并将显示所有当前可用的自定义帖子类型。选择并设置需要显示的选项,然后单击“更新”。您的页面现在将显示您选择的自定义帖子类型中的帖子,并且您的页面将在导航栏中可见。
您可以在此基础上添加更多功能,或者更改代码以同样的方式显示类别或分类。希望这有帮助