我有一个客户的网站,该网站将大量使用自定义帖子类型来配置其网站。但是对于他们要求的主页,我却是一团糟。

实际上,主页将是WordPress中特定“页面”的堆栈。基本上,将有以下页面:简介,博客,关于我们,投资组合和联系我们。它们将全部堆叠在一起,以便您可以从一页滚动到另一页。

我的第一个直觉是仅使用一个页面(称为“主页”)并嵌入一个接受页面信息的简码。并输出正确的顺序(即[pageOrder]intro, blog, about-us, portfolio, contact-us[/pageOrder])。该页面将使用自定义页面模板来布置内容,控制循环并将导航添加到页面左侧。但这一切似乎都是笨拙的。

我理想的解决方案是创建一个自定义帖子类型(称为Stack),该类型允许最终用户通过拖放操作定位页面并让CPT负责布局和导航等。

我理想的解决方案的问题是设置。 WordPress允许您为网站的默认主页选择页面。但这与帖子的页面类型有关,我不确定在何处进行修改以使用户也可以选择堆栈作为默认主页。

那么,我在哪里可以挂钩以将CPT添加到默认主页的可用页面下拉菜单中?

#1 楼

感谢@toscho给出了有用的答案,但对我来说却有点琐,所以我摸索了一下,发现我可以改为添加过滤器:
function wpa18013_add_pages_to_dropdown( $pages, $r ){
    if('page_on_front' == $r['name']){
        $args = array(
            'post_type' => 'stack'
        );
        $stacks = get_posts($args);
        $pages = array_merge($pages, $stacks);
    }

    return $pages;
}
add_filter( 'get_pages', 'wpa18013_add_pages_to_dropdown', 10, 2 );


更新
添加上述代码后,我的确可以使用自定义帖子类型作为主页,但是WordPress会重定向永久链接,因为它不是“页面”帖子类型。因此,http://localhost/test将重定向到http://localhost/test/stacks/home-stack,这不是我想要的。
尽管添加了此操作,但已修复该问题并查询了我的自定义帖子类型以及主页页面:
function enable_front_page_stacks( $query ){
    if('' == $query->query_vars['post_type'] && 0 != $query->query_vars['page_id'])
        $query->query_vars['post_type'] = array( 'page', 'stack' );
}
add_action( 'pre_get_posts', 'enable_front_page_stacks' );


评论


我也使用过这样的过滤器,但必须仅限于首页查询。然后我被一些奇怪的行为/错误打败:我只有404。无论如何+1。 :)

– fuxia♦
11年5月24日在1:49

接得好。函数内部的附加条件(确保尚未设置post_type且page_id不为0)可防止所有404。现在,我可以对我的所有自定义帖子,所有帖子以及所有页面运行查询,而不会受到任何干扰。

–EAMann
2011年5月24日下午4:39

@EAmann感谢您的代码!尽管它将首页的标题更改为“帖子标题|标题”,但它仍应能正常工作。主页名称,是否可以将其更改为只是主页名称?

– INT
2012年7月11日下午0:38

这根本不起作用...服务器警告/错误:wpa18013_add_pages_to_dropdown()和未定义变量的参数2缺失:r

– Dameer
13-10-22在11:16



@EAMann我对此有误。如果设置设置为“您的最新帖子”,则在首页上显示“未定义索引post_type”,在其他页面上,我会收到“未定义索引:名称”的其他错误

–基督教徒
20-5-20在20:19



#2 楼

可能是吧?我以前的解决方案的改进版本。

add_filter( 'wp_dropdown_pages', 'add_cpt_to_front_page_dropdown', 10, 1 );


/**
 * Adds CPTs to the list of available pages for a static front page.
 *
 * @param  string $select Existing select list.
 * @return string
 */
function add_cpt_to_front_page_dropdown( $select )
{
    if ( FALSE === strpos( $select, '<select name="page_on_front"' ) )
    {
        return $select;
    }

    $cpt_posts = get_posts(
        array(
            'post_type'      => 'YOUR_POST_TYPE'
        ,   'nopaging'       => TRUE
        ,   'numberposts'    => -1
        ,   'order'          => 'ASC'
        ,   'orderby'        => 'title'
        ,   'posts_per_page' => -1
        )
    );

    if ( ! $cpt_posts ) // no posts found.
    {
        return $select;
    }

    $current = get_option( 'page_on_front', 0 );

    $options = walk_page_dropdown_tree(
        $cpt_posts
    ,   0
    ,    array(
            'depth'                 => 0
         ,  'child_of'              => 0
         ,  'selected'              => $current
         ,  'echo'                  => 0
         ,  'name'                  => 'page_on_front'
         ,  'id'                    => ''
         ,  'show_option_none'      => ''
         ,  'show_option_no_change' => ''
         ,  'option_none_value'     => ''
        )
    );

    return str_replace( '</select>', $options . '</select>', $select );
}


评论


这仅用于选择自定义帖子类型,但这不会使该自定义帖子类型显示为首页吗?还是我错过了什么?

–汉密杜拉汗
2011年5月23日在18:23

@Hameedullah-选择它后,WordPress将更新一个选项,该选项标记应将哪个页面用于首页。然后,当用户访问首页时,WordPress从数据库读回相同的选项。

–EAMann
2011年5月23日在18:49

@Hameedullah Khan你是对的。这在3.1之前有效,现在我重定向到该帖子的永久链接–我得到404。奇怪。我希望我有时间。 :(

– fuxia♦
11年5月23日在20:06

#3 楼

为什么不只创建一个front-page.php模板文件,该文件使用常规查询/循环,或者(如果将自定义主题选项设置为在首页上显示CPT),则基于CPT输出自定义查询/循环? br />
出现的问题是,您必须创建一个单独的Theme选项来控制Front Page的输出,同时指示用户将Front Page设置为静态页面。

为使事情变得更简单,您可以通过“设置API”使用register_setting调用中的“阅读”选项组,将“主题”选项挂接到“设置阅读”中,以使其与现有的“首页”选项一起显示。

评论


我喜欢简单的解决方案,Chip我认为您的最好。 WordPress允许为首页codex.wordpress.org/Template_Hierarchy#Home_Page_display自定义模板,然后人们可以在其中执行任何操作。

– anmari
2011年10月12日上午10:12

这是最可维护和最直接的解决方案。由于front-page.php是wordpress模板层次结构的一部分,因此会自动选择。无需记住发生这种情况的原因(或需要将其标记为下一个人)。

–奥德斯
2014年11月2日14:25

#4 楼

我认为自从EAMann在2011年编写更新以来,情况可能已经有所改变,并且他提供的wpa18013_add_pages_to_dropdown()函数不再起作用。如Dameer的评论中所述,此函数当前(2013年12月)引发错误“ wpa18013_add_pages_to_dropdown()缺少参数2”

对我来说,解决方案是重写函数而不用第二秒参数,或检查其内容。然后,完整的代码块变为:

function add_unbox_tabs_to_dropdown( $pages ){
    $args = array(
        'post_type' => 'unbox_tabs'
    );
    $items = get_posts($args);
    $pages = array_merge($pages, $items);

    return $pages;
}
add_filter( 'get_pages', 'add_unbox_tabs_to_dropdown' );

function enable_front_page_unbox_tabs( $query ){
    if('' == $query->query_vars['post_type'] && 0 != $query->query_vars['page_id'])
        $query->query_vars['post_type'] = array( 'page', 'unbox_tabs' );
}
add_action( 'pre_get_posts', 'enable_front_page_unbox_tabs' );


请注意,在上面的示例中,我添加的自定义帖子类型是“ unbox_tabs”而不是“ stack” 。

#5 楼

我正在使用这种技术来包含来自插件的模板。因此,@ ChipBennett的解决方案不适用。

要从“静态页面”列表的插件中添加CPT('hierarchical' => 'false'),我对@EAMann的解决方案进行了如下修改:

add_action( 'admin_head-options-reading.php', 'wpse_18013_modify_front_pages_dropdown' );
add_action( 'pre_get_posts', 'wpse_18013_enable_front_page_stacks' );

function wpse_18013_modify_front_pages_dropdown()
{
    // Filtering /wp-includes/post-templates.php#L780
    add_filter( 'get_pages', 'wpse_18013_add_cpt_to_pages_on_front' );
}

function wpse_18013_add_cpt_to_pages_on_front( $r )
{
    $args = array(
        'post_type' => 'stack'
    );
    $stacks = get_posts( $args );
    $r = array_merge( $r, $stacks );

    return $r;
}

function wpse_18013_enable_front_page_stacks( $query )
{
    if( '' == $query->query_vars['post_type'] && 0 != $query->query_vars['page_id'] )
        $query->query_vars['post_type'] = array( 'page', 'stack' );
}



/**
 * wp-admin/options-reading.php#L96
 * Happens inside a <li><label>-</label></li>
 */
    wp_dropdown_pages( array( 
                'name' => 'page_on_front'
            ,   'echo' => 0
            ,   'show_option_none' => __( '&mdash; Select &mdash;' )
            ,   'option_none_value' => '0'
            ,   'selected' => get_option( 'page_on_front' ) 
        ) 
    )

/**
  * wp-includes/post-template.php#L768
  */
function wp_dropdown_pages($args = '') {
    $defaults = array( /* defaults array */ );    
    $r = wp_parse_args( $args, $defaults );
    extract( $r, EXTR_SKIP );  
    $pages = get_pages( $r );