作为自定义发布类型档案的页面模板

时间:2015-03-23 作者:wackerfuss

我的目标是拥有slug www.domain。com/a使用的资源Page Template 而不是Archive Page, 并且有一个CPT岗位作为该slug的子岗位,例如www.domain.com/resources/post.

我认为可行的解决方案:

我在Wordpress中创建了一个新页面,并为其提供了一个自定义页面模板。我还注册了我的自定义帖子类型,如下所示。特别注意has\\u归档和重写:

function bb_resources() {
    register_post_type( \'resources\', array(
            \'labels\' => array(
                    \'name\' => \'Resources\',
                    \'singular_name\' => \'Resource\',
            ),
            \'taxonomies\' => array(\'resources_cat\'),
            \'public\' => true,
            \'has_archive\' => false,
            \'show_ui\' => true,
            \'supports\' => array( \'title\', \'editor\' ),
            \'rewrite\' => array(\'slug\'=>\'resources\', \'with_front\'=>false),
    ) );
}
然而,这在单个帖子页面上创建了404。

我被难住了,请告诉我!

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

自WordPress版本4.4起\'theme_page_templates\' 允许设置任意页面模板。

这意味着可以在页面编辑屏幕的“页面模板”菜单中显示任意值,选择后,该值将存储在页面的页面模板元中。

这意味着您可以“自动”为任何注册的CPT创建页面模板。

设置页面模板代码如下所示:

add_action( \'current_screen\', function( \\WP_Screen $screen ) {
    if( \'page\' !== $screen->id || \'post\' !== $screen->base ) {
        return;
    }

    // retrieve CPT objects with archive
    $types = get_post_types( [\'has_archive\' => true], \'objects\' );

    // store CPT slug and labels in an array
    $menu = array();
    foreach( $types as $cpt ) {
        $menu[ $cpt->name ] = \'Archive: \' . $cpt->label;
    }

    // merge with page templates
    $menu and add_filter(
        \'theme_page_templates\',
        function( array $templates ) use ( $menu ) {
            $templates = array_merge( $templates, $menu );
            return $templates;
        }
    );
} );
使用此代码,假设您注册了一个帖子类型resources 具有has_archive 设置为true, 创建或编辑页面时,您将在“页面模板”下拉列表中看到一个名为Archive: Resources.

您可以在创建页面时选择要用于显示resources 职位。

重定向直接页面访问

由于此页面是一个归档文件而不是一个页面,因此在访问页面时,可以使用一些代码将用户重定向到实际CPT的归档文件:

add_action( \'template_redirect\', function() {
    if( is_page_template() ) {

        // current page templates
        $template = get_page_template_slug( get_queried_object_id() );

        // array of CPT names, filtering the ones with archives
        $types = get_post_types( array( \'has_archive\' => true ), \'names\' );

        // if the current template is one of the CPT, redirect
        if( in_array( $template, $types, true ) ) {
            wp_safe_redirect( get_post_type_archive_link( $template ) );
            exit();
        }
    }
} );
获取页面数据查看文章时,您可能希望使用该页面的内容和标题。

那么,让我们编写一个函数,用于获取特定帖子类型的页面。

function get_archive_page( $post_type = \'\' ) {

    // if no CPT given, let\'s use the current main query to get it
    if( ! $post_type ) {
        global $wp_query;
        $query_var = ( array ) $wp_query->get( \'post_type\' );
        $post_type = reset($query_var);
    }

    // if we have a valid post type
    if( post_type_exists( $post_type ) ) {

        // let\'s query the first page that has a page template
        // named after the the post type
        $posts = get_posts( array(
            \'post_type\'      => \'page\',
            \'post_status\'    => \'publish\',
            \'posts_per_page\' => 1,
            \'orderby\'        => \'menu_order\',
            \'order\'          => \'ASC\',
            \'meta_query\' => array( array( 
                \'key\'   => \'_wp_page_template\',
                \'value\' => $post_type
            ) )
        ) );

        // if we have results, return first (and only) post object
        if( $posts ) {
            return reset($posts);
        }
    }
}
您可以使用上面的函数编写两个附加函数来获取页面的标题和内容:

function get_archive_page_title( $post_type = \'\' ) {
    $page = get_archive_page( $post_type );

    return ( $page ) ? get_the_title( $page ) : \'\';
}    

function get_archive_page_content( $post_type = \'\' ) {
    $page       = get_archive_page( $post_type );
    $content    = \'\';

    if( $page ) {
        setup_postdata( $page );
        ob_start();
            the_content();
        $content = ob_get_clean();
        wp_reset_postdata();
    }

    return $content;
}

function the_archive_page_title() {
    echo get_archive_page_title();
}

function the_archive_page_content() {
    echo get_archive_page_content();
}
函数名应该明确它们的作用。

您还可以编写如下函数get_archive_page_meta() 如果需要自定义字段。

现在,在存档模板中archive.php (或在archive-resources.php) 模板中,您可以使用上述功能显示存档页面的标题和内容。

它看起来像:

<h1><?php the_archive_page_title(); ?></h1>

<div><?php the_archive_page_content(); ?></div>

<?php
    while( have_posts() ) : the_post();
        // loop stuff here
    endwhile;
?>
这样,您的CPT存档url将example.com/resources/ 您的单个CPT url将是example.com/resources/post-name/ 就像你想要的那样。

同时,您将能够为帖子类型编写特定的内容和标题(以及自定义字段,如果需要的话)。

此外,请考虑此方法对于您已经或将来可能使用的任何post类型都是可重用的。

SO网友:kraftner

gmazzap\'sanswer 太棒了!我只想补充一下,自4.1以来,有两个新函数完全适合该用例:the_archive_titlethe_archive_description. 对于已经使用这些模板的主题(如215),您可以跳过最后一部分编辑主题模板,改为执行以下操作:

通过过滤器添加数据

add_filter( \'get_the_archive_title\', function( $title ) {
    if( is_post_type_archive() ) {   
        $page  = get_archive_page( $post_type );    // Function Found in @gmazzap\'s answer
        $title = $page ? get_the_title( $page ) : $title;
    }

    return $title;
} );

add_filter( \'get_the_archive_description\', function( $content ) {
    if( is_post_type_archive() ) {
        $page    = get_archive_page( $post_type );  // Function Found in @gmazzap\'s answer
        $content = \'\';

        if( $page ) {
            setup_postdata( $page );
            ob_start();
                the_content();
            $content = ob_get_clean();
            wp_reset_postdata();
        }

        $content = ( $content !== \'\' ) ? get_the_title( $page ) : $content;
    }

    return $content;
} );

SO网友:Will

在阅读了前两个答案后,我自己的方法肯定感觉像是穴居人,但我还是要分享它,因为虽然它不那么健壮,但它的设置却非常容易。它还使内容作者很容易知道在一个主要基于页面/CMS风格的网站结构中,在哪里编辑给定存档的“概述”内容。

对于名为region 我会将其与一个名为regions.

创建名为page-regions.php (或者使用任何策略将其连接到该页面)并执行自定义循环以提取所有region post\\u类型。如果您将模板部分用于模板,那么很容易包含页眉和主体,这样代码就不会变干。它也很容易定制,因为总是有一种post\\u类型。:)

这样,URL将与您要求的略有不同:

http://example.com/regions 对于包含存档帖子和
http://example.com/region/africa
http://example.com/region/asia 对于单个CPT视图。

但对我来说,/region/africa 实际上比/regions/africa 尽管这可能是在rails/cakephp网站上工作的结果,在这些网站上这是正常的。/region 只有post\\u type=区域存档(取决于您如何设置post\\u类型),而没有页面中的概述内容,但我只是不链接到它。如果URL栏冲浪者到了那里,没什么大不了的。

轻微的次要好处:您可以根据需要创建概述/归档页面的URL,例如/regions-of-the-world.

结束

相关推荐

作为自定义发布类型档案的页面模板 - 小码农CODE - 行之有效找到问题解决它

作为自定义发布类型档案的页面模板

时间:2015-03-23 作者:wackerfuss

我的目标是拥有slug www.domain。com/a使用的资源Page Template 而不是Archive Page, 并且有一个CPT岗位作为该slug的子岗位,例如www.domain.com/resources/post.

我认为可行的解决方案:

我在Wordpress中创建了一个新页面,并为其提供了一个自定义页面模板。我还注册了我的自定义帖子类型,如下所示。特别注意has\\u归档和重写:

function bb_resources() {
    register_post_type( \'resources\', array(
            \'labels\' => array(
                    \'name\' => \'Resources\',
                    \'singular_name\' => \'Resource\',
            ),
            \'taxonomies\' => array(\'resources_cat\'),
            \'public\' => true,
            \'has_archive\' => false,
            \'show_ui\' => true,
            \'supports\' => array( \'title\', \'editor\' ),
            \'rewrite\' => array(\'slug\'=>\'resources\', \'with_front\'=>false),
    ) );
}
然而,这在单个帖子页面上创建了404。

我被难住了,请告诉我!

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

自WordPress版本4.4起\'theme_page_templates\' 允许设置任意页面模板。

这意味着可以在页面编辑屏幕的“页面模板”菜单中显示任意值,选择后,该值将存储在页面的页面模板元中。

这意味着您可以“自动”为任何注册的CPT创建页面模板。

设置页面模板代码如下所示:

add_action( \'current_screen\', function( \\WP_Screen $screen ) {
    if( \'page\' !== $screen->id || \'post\' !== $screen->base ) {
        return;
    }

    // retrieve CPT objects with archive
    $types = get_post_types( [\'has_archive\' => true], \'objects\' );

    // store CPT slug and labels in an array
    $menu = array();
    foreach( $types as $cpt ) {
        $menu[ $cpt->name ] = \'Archive: \' . $cpt->label;
    }

    // merge with page templates
    $menu and add_filter(
        \'theme_page_templates\',
        function( array $templates ) use ( $menu ) {
            $templates = array_merge( $templates, $menu );
            return $templates;
        }
    );
} );
使用此代码,假设您注册了一个帖子类型resources 具有has_archive 设置为true, 创建或编辑页面时,您将在“页面模板”下拉列表中看到一个名为Archive: Resources.

您可以在创建页面时选择要用于显示resources 职位。

重定向直接页面访问

由于此页面是一个归档文件而不是一个页面,因此在访问页面时,可以使用一些代码将用户重定向到实际CPT的归档文件:

add_action( \'template_redirect\', function() {
    if( is_page_template() ) {

        // current page templates
        $template = get_page_template_slug( get_queried_object_id() );

        // array of CPT names, filtering the ones with archives
        $types = get_post_types( array( \'has_archive\' => true ), \'names\' );

        // if the current template is one of the CPT, redirect
        if( in_array( $template, $types, true ) ) {
            wp_safe_redirect( get_post_type_archive_link( $template ) );
            exit();
        }
    }
} );
获取页面数据查看文章时,您可能希望使用该页面的内容和标题。

那么,让我们编写一个函数,用于获取特定帖子类型的页面。

function get_archive_page( $post_type = \'\' ) {

    // if no CPT given, let\'s use the current main query to get it
    if( ! $post_type ) {
        global $wp_query;
        $query_var = ( array ) $wp_query->get( \'post_type\' );
        $post_type = reset($query_var);
    }

    // if we have a valid post type
    if( post_type_exists( $post_type ) ) {

        // let\'s query the first page that has a page template
        // named after the the post type
        $posts = get_posts( array(
            \'post_type\'      => \'page\',
            \'post_status\'    => \'publish\',
            \'posts_per_page\' => 1,
            \'orderby\'        => \'menu_order\',
            \'order\'          => \'ASC\',
            \'meta_query\' => array( array( 
                \'key\'   => \'_wp_page_template\',
                \'value\' => $post_type
            ) )
        ) );

        // if we have results, return first (and only) post object
        if( $posts ) {
            return reset($posts);
        }
    }
}
您可以使用上面的函数编写两个附加函数来获取页面的标题和内容:

function get_archive_page_title( $post_type = \'\' ) {
    $page = get_archive_page( $post_type );

    return ( $page ) ? get_the_title( $page ) : \'\';
}    

function get_archive_page_content( $post_type = \'\' ) {
    $page       = get_archive_page( $post_type );
    $content    = \'\';

    if( $page ) {
        setup_postdata( $page );
        ob_start();
            the_content();
        $content = ob_get_clean();
        wp_reset_postdata();
    }

    return $content;
}

function the_archive_page_title() {
    echo get_archive_page_title();
}

function the_archive_page_content() {
    echo get_archive_page_content();
}
函数名应该明确它们的作用。

您还可以编写如下函数get_archive_page_meta() 如果需要自定义字段。

现在,在存档模板中archive.php (或在archive-resources.php) 模板中,您可以使用上述功能显示存档页面的标题和内容。

它看起来像:

<h1><?php the_archive_page_title(); ?></h1>

<div><?php the_archive_page_content(); ?></div>

<?php
    while( have_posts() ) : the_post();
        // loop stuff here
    endwhile;
?>
这样,您的CPT存档url将example.com/resources/ 您的单个CPT url将是example.com/resources/post-name/ 就像你想要的那样。

同时,您将能够为帖子类型编写特定的内容和标题(以及自定义字段,如果需要的话)。

此外,请考虑此方法对于您已经或将来可能使用的任何post类型都是可重用的。

SO网友:kraftner

gmazzap\'sanswer 太棒了!我只想补充一下,自4.1以来,有两个新函数完全适合该用例:the_archive_titlethe_archive_description. 对于已经使用这些模板的主题(如215),您可以跳过最后一部分编辑主题模板,改为执行以下操作:

通过过滤器添加数据

add_filter( \'get_the_archive_title\', function( $title ) {
    if( is_post_type_archive() ) {   
        $page  = get_archive_page( $post_type );    // Function Found in @gmazzap\'s answer
        $title = $page ? get_the_title( $page ) : $title;
    }

    return $title;
} );

add_filter( \'get_the_archive_description\', function( $content ) {
    if( is_post_type_archive() ) {
        $page    = get_archive_page( $post_type );  // Function Found in @gmazzap\'s answer
        $content = \'\';

        if( $page ) {
            setup_postdata( $page );
            ob_start();
                the_content();
            $content = ob_get_clean();
            wp_reset_postdata();
        }

        $content = ( $content !== \'\' ) ? get_the_title( $page ) : $content;
    }

    return $content;
} );

SO网友:Will

在阅读了前两个答案后,我自己的方法肯定感觉像是穴居人,但我还是要分享它,因为虽然它不那么健壮,但它的设置却非常容易。它还使内容作者很容易知道在一个主要基于页面/CMS风格的网站结构中,在哪里编辑给定存档的“概述”内容。

对于名为region 我会将其与一个名为regions.

创建名为page-regions.php (或者使用任何策略将其连接到该页面)并执行自定义循环以提取所有region post\\u类型。如果您将模板部分用于模板,那么很容易包含页眉和主体,这样代码就不会变干。它也很容易定制,因为总是有一种post\\u类型。:)

这样,URL将与您要求的略有不同:

http://example.com/regions 对于包含存档帖子和
http://example.com/region/africa
http://example.com/region/asia 对于单个CPT视图。

但对我来说,/region/africa 实际上比/regions/africa 尽管这可能是在rails/cakephp网站上工作的结果,在这些网站上这是正常的。/region 只有post\\u type=区域存档(取决于您如何设置post\\u类型),而没有页面中的概述内容,但我只是不链接到它。如果URL栏冲浪者到了那里,没什么大不了的。

轻微的次要好处:您可以根据需要创建概述/归档页面的URL,例如/regions-of-the-world.

相关推荐