如何将自定义帖子类型的帖子设置为静态首页?

时间:2016-01-21 作者:Bunjip

我正在从头开始写我的自定义主题,我有一个自定义帖子类型“my\\u frontpage”,并想将其中一篇帖子声明为首页。我想通过admin完成这项工作,因此只需将我的cpt添加到静态首页的选择框中即可。

这个问题在互联网上已经讨论过好几次了。然而,我找不到如何全面解释实现这一目标的所有步骤的指示。

到目前为止,我知道我需要使用某种钩子来扩展可用头版“页面”的选择,其中包含来自我的cpt的帖子。但是要用哪个钩子呢?我甚至不知道,如果我必须使用动作或过滤器挂钩?那么,有人能用外行的话来指导我解决这个问题吗?

我能找到的最接近的结果是This question. 然而,我还不能完全理解那里发生了什么。。。

3 个回复
最合适的回答,由SO网友:Pieter Goosen 整理而成

我有时间看看你的问题options-reading.php 页面,它是用于在后端呈现阅读设置页面的模板。

遗憾的是,在可选择的下拉列表中,没有过滤器可以过滤或添加自定义帖子作为粘滞帖子。我们可以使用两个隐藏的过滤器,它们是

  • wp_dropdown_pages 内部wp_dropdown_pages() function 用于显示可设置为静态首页的页面列表的下拉列表

  • get_pages 内部get_pages() function 哪个功能负责返回所使用的页面wp_dropdown_pages()

    我想是的get_pages 这里有一个更好的选择。这样我们就可以wp_dropdown_pages() 处理所有标记。但是,当我们使用get_pages 滤器

    我们需要确保只针对管理区域,尤其是阅读设置页面,否则我们将更改使用get_pages() 功能

您需要决定是需要使用自定义帖子类型的帖子显示页面,还是只需要自定义帖子类型

您可以尝试以下操作:

add_filter( \'get_pages\', function ( $pages, $args )
{
    // First make sure this is an admin page, if not, bail
    if ( !is_admin() )
        return $pages;

    // Make sure that we are on the reading settings page, if not, bail
    global $pagenow;
    if ( \'options-reading.php\' !== $pagenow )
        return $pages;

    // Remove the filter to avoid infinite loop
    remove_filter( current_filter(), __FUNCTION__ );

    $args = [
        \'post_type\'      => \'my_frontpage\',
        \'posts_per_page\' => -1
    ];
    // Get the post type posts with get_posts to allow non hierarchical post types
    $new_pages = get_posts( $args );    

    /**
     * You need to decide if you want to add custom post type posts to the pages
     * already in the dropdown, or just want the custom post type posts in
     * the dropdown. I will handle both, just remove what is not needed
     */
    // If we only need custom post types
    $pages = $new_pages;

    // If we need to add custom post type posts to the pages
    // $pages = array_merge( $new_pages, $pages );

    return $pages;
}, 10, 2 );
现在,您应该可以在下拉列表中看到自定义帖子类型的帖子。请注意,此代码也会影响博客页面的下拉列表。

为了避免这种情况,您可以使用静态计数器来计算过滤器运行的次数,然后在过滤器应用于blogpage下拉列表之前退出。过滤器将总共运行3次,如下所示:get_pages() 运行3次:

首先检查我们是否确实有页面设置为静态首页。

第二次跑步将在室内进行wp_dropdown_pages() 静态首页下拉列表使用

最后一次跑步将在wp_dropdown_pages() blogpage下拉列表使用的

因此,基于此,我们可以尝试

add_filter( \'get_pages\', function ( $pages, $args )
{
    // First make sure this is an admin page, if not, bail
    if ( !is_admin() )
        return $pages;

    // Make sure that we are on the reading settings page, if not, bail
    global $pagenow;
    if ( \'options-reading.php\' !== $pagenow )
        return $pages;

    // Remove the filter to avoid infinite loop
    remove_filter( current_filter(), __FUNCTION__ );

    // Setup our static counter
    static $counter = 0;

    // Bail on the third run all runs after this. The third run will be 2
    if ( 2 <= $counter )
        return $pages;

    // Update our counter
    $counter++;

    $args = [
        \'post_type\'      => \'my_frontpage\',
        \'posts_per_page\' => -1
    ];
    // Get the post type posts with get_posts to allow non hierarchical post types
    $new_pages = get_posts( $args );    

    /**
     * You need to decide if you want to add custom post type posts to the pages
     * already in the dropdown, or just want the custom post type posts in
     * the dropdown. I will handle both, just remove what is not needed
     */
    // If we only need custom post types
    $pages = $new_pages;

    // If we need to add custom post type posts to the pages
    // $pages = array_merge( $new_pages, $pages );

    return $pages;
}, 10, 2 );
如果您访问前端并访问首页,您会发现它将重定向到单个贴子页。这是因为,默认情况下,静态首页上的主查询设置为查询page 岗位类型。这会导致返回404redirect_canonical() 然后重定向到单篇文章页面。这很容易解决,我们所要做的就是调整静态首页上的主查询。

add_action( \'pre_get_posts\', function ( $q )
{
    if (    !is_admin() // Only target the front end
         && $q->is_main_query() // Only target the main query
         && \'page\' === get_option( \'show_on_front\' ) // Only target the static front page
    ) {
        $q->set( \'post_type\', \'my_frontpage\' );
    }
});
现在,静态首页将正确显示。

您只需设置一个模板。您只需创建front-page.php, WordPress将自动使用它

SO网友:Bunjip

虽然Pieter毫无疑问地优雅而全面地解决了这个问题,但我最终还是选择了另一个解决方案,我也想在这里分享一下。也许有些人在将来会面临类似的问题。

对于我的问题中描述的自定义帖子类型定义,我使用了一个名为Pods. 由于插件开发人员和社区可能会定期处理自定义的帖子类型,我认为在他们的支持渠道中问我的问题可能也会有所帮助。

Pods开发团队的一位非常有帮助的人为我指明了方向,我最终选择了。因此,与其为了创建高度个性化的静态首页而定义自定义帖子类型,他建议在标准页面中添加自定义字段,而标准页面应该成为首页。这就是我为实现目标所做的,也是我向其他用户推荐的。

从数据建模的角度来看,如果您只想将其应用于单个项目,那么没有理由定义一个完整的数据类型或类,在我的例子中是一个单一的首页。我使用了另一个插件,名为Advanced Custom Fields, 因为这允许自定义字段使用比Wordpress提供的现成数据类型更高级的数据类型。您可以通过函数添加自定义字段。php也是如此。希望,这会有所帮助。

SO网友:cruzquer

还有另外一种方法可以避免使用页面模板,让Wordpress通过使用正确的帖子类型模板来加载首页。如果您想让头版对单个帖子本身看起来一样,这有助于避免重复代码:

add_filter( \'template_include\', \'add_front_page_template_path\', 10, 1);

function add_front_page_template_path( $template_path ) {
    if (
        is_front_page() 
        && get_option( \'show_on_front\' ) == \'page\' 
        && ( $post_id = get_option( \'page_on_front\' ) )
        && ( $post_type = get_post_type( $post_id ) ) != \'page\' 
    ) {
        $_template_path = get_single_template( $post_type );

        /* In case there’s no template */
        $template_path = ( $template_path == \'\' ) ? $template_path : $_template_path;
    }

    return $template_path;  
}