我最喜欢的Wordpress模板层次结构部分是能够通过slug快速创建页面的模板文件,而不必在Wordpress中编辑页面以选择模板。

我们目前可以执行以下操作:
/>

页面-{slug} .php


但是我希望能够做到这一点:


single- {post_type}-{slug} .php


因此,例如,在名为review的帖子类型中,我可以为名为“我的伟大”的帖子制作模板请参阅single-review-my-great-review.php上的“评论”。

以前有人设置过吗? single-{post_type}-{slug}.php

评论

以前从未使用过这样的设置,但是如果它太复杂了,为什么不制作一个模板文件并将其与相关的评论相关联呢?

WP 3.4自动获取单个{{post_type}-{slug} .php,因此升级到WP 3.4是另一种选择。

#1 楼

A)核心基础

在Codex模板层次结构说明中可以看到,已经支持single-{$post_type}.php


B)扩展核心层次结构

现在很高兴在/wp-includes/template-loader.php内有一些过滤器和钩子。


B.1)工作方式


在模板加载器文件中,模板由条件var / wp_query查询加载:do_action('template_redirect');
然后条件触发(如果是“单个”模板):apply_filters( 'template_include', $template )

然后触发get_query_template( $type, ... ),其中"$type}_template"is_*()

那么我们有了is_single() && $template = get_single_template()过滤器


C)解决方案

由于我们只想使用在实际get_query_template( $type, $templates )模板之前加载的一个模板扩展层次结构,因此我们将拦截层次结构并将新模板添加到模板数组的开头。

// Extend the hierarchy
function add_posttype_slug_template( $templates )
{

    $object = get_queried_object();

    // New 
    $templates[] = "single-{$object->post_type}-{$object->post_name}.php";
    // Like in core
    $templates[] = "single-{$object->post_type}.php";
    $templates[] = "single.php";

    return locate_template( $templates );    
}
// Now we add the filter to the appropriate hook
function intercept_template_hierarchy()
{
    add_filter( 'single_template', 'add_posttype_slug_template', 10, 1 );
}
add_action( 'template_redirect', 'intercept_template_hierarchy', 20 );
<注释:(如果您要使用默认对象以外的其他东西),则必须根据固定链接结构调整$type。只需使用全局single中的任何内容即可。火车票清单:


使用post_type-> slug扩展层次结构
引入"{$type}_template"的过滤器

过滤整个层次结构-最有希望票证&lBarr; @scribu以cc


的身份将此票关注

评论


我想对此进行测试,但看起来您的add_filter行最后缺少一些内容。

–超真实
2012年2月2日在20:45



@supertrue好抓住。 :)在过滤器中发现另一个缺少的)。固定。也许您想在模板内的嵌条之前用下划线替换破折号。只是为了在查看模板时使后缀更加突出。

– kaiser
2012年2月2日在22:01



在整个网站上导致此错误:警告:array_unshift()[function.array-unshift]:第一个参数应该是[包含array_unshift的行中的一个数组

–超真实
2012年2月4日,0:02



好的,但是接下来还有其他事情要拦截核心模板。该函数可以正常工作,并且$ templates是一个数组。请参阅此pastebin中的核心功能(无有效期)。确保使用不带插件和默认主题的安装进行测试。然后一个接一个地激活,看看错误是否仍然出现。

– kaiser
2012年2月4日在0:47



是的,我调试了这个,我得到了第一个找到的模板的最终绝对路径作为字符串。在更改答案之前,我将不得不与一些核心开发人员进行讨论。另外:我混合了一些东西:子词仅适用于术语和分类法。您应该用适合您的永久链接结构的方式替换$ post-> post_name。当前,无法根据情况永久地自动执行此操作,这取决于您的永久结构和重写规则。期待另一个更新。

– kaiser
2012年2月4日在1:19



#2 楼

在“模板层次结构”图像之后,我看不到这样的选项。

以下是我的处理方法:

解决方案1(我认为最好)

制作模板文件并将其关联到评论

 <?php
 /*
 Template Name: My Great Review
 */
 ?>


将模板php文件添加到主题目录中,它将作为模板选项出现在帖子的编辑页面中。

解决方案2

可以使用template_redirect钩子来实现。编辑

添加了file_exists检查

评论


你为什么要退出?那里?

– kaiser
2012年2月2日在18:26

@kaiser一定在我当时遵循的任何教程中,如果没有必要,我将其删除。

– Shane
2012年2月2日,19:48



@kaiser:exit()对于防止加载默认模板是必需的。

–抄写员
2012年2月3日,0:30

解决方案1仅适用于页面,不适用于帖子。

–IXN
2015年11月7日,12:18

#3 楼

最佳答案(来自4年前)不再起作用,但是WordPress代码库在此处提供了解决方案:

<?php
function add_posttype_slug_template( $single_template )
{
    $object = get_queried_object();
    $single_postType_postName_template = locate_template("single-{$object->post_type}-{$object->post_name}.php");
    if( file_exists( $single_postType_postName_template ) )
    {
        return $single_postType_postName_template;
    } else {
        return $single_template;
    }
}
add_filter( 'single_template', 'add_posttype_slug_template', 10, 1 );
?>


#4 楼

使用页面模板

另一种可扩展性的方法是将page帖子类型上的页面模板下拉功能复制为自定义帖子类型。

可重用的代码

代码中的重复不是一个好习惯。超时会导致代码库严重膨胀,从而使开发人员难以管理。除了很可能不需要为每个块创建模板之外,您还可能需要可以重用的一对多模板,而不是一对一的后置模板。

代码

# Define your custom post type string
define('MY_CUSTOM_POST_TYPE', 'my-cpt');

/**
 * Register the meta box
 */
add_action('add_meta_boxes', 'page_templates_dropdown_metabox');
function page_templates_dropdown_metabox(){
    add_meta_box(
        MY_CUSTOM_POST_TYPE.'-page-template',
        __('Template', 'rainbow'),
        'render_page_template_dropdown_metabox',
        MY_CUSTOM_POST_TYPE,
        'side', #I prefer placement under the post actions meta box
        'low'
    );
}

/**
 * Render your metabox - This code is similar to what is rendered on the page post type
 * @return void
 */
function render_page_template_dropdown_metabox(){
    global $post;
    $template = get_post_meta($post->ID, '_wp_page_template', true);
    echo "
        <label class='screen-reader-text' for='page_template'>Page Template</label>
            <select name='_wp_page_template' id='page_template'>
            <option value='default'>Default Template</option>";
            page_template_dropdown($template);
    echo "</select>";
}

/**
 * Save the page template
 * @return void
 */
function save_page_template($post_id){

    # Skip the auto saves
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
        return;
    elseif ( defined( 'DOING_AJAX' ) && DOING_AJAX )
        return;
    elseif ( defined( 'DOING_CRON' ) && DOING_CRON )
        return;

    # Only update the page template meta if we are on our specific post type
    elseif(MY_CUSTOM_POST_TYPE === $_POST['post_type'])
        update_post_meta($post_id, '_wp_page_template', esc_attr($_POST['_wp_page_template']));
}
add_action('save_post', 'save_page_template');


/**
 * Set the page template
 * @param string $template The determined template from the WordPress brain
 * @return string $template Full path to predefined or custom page template
 */
function set_page_template($template){
    global $post;
    if(MY_CUSTOM_POST_TYPE === $post->post_type){
        $custom_template = get_post_meta($post->ID, '_wp_page_template', true);
        if($custom_template)
            #since our dropdown only gives the basename, use the locate_template() function to easily find the full path
            return locate_template($custom_template);
    }
    return $template;
}
add_filter('single_template', 'set_page_template');


这是一个较晚的答案,但我认为这将是有价值的,因为据我所知,网络上尚无人记录这种方法。希望这可以帮助某人。

#5 楼

就我而言,我具有“专辑”分类法链接的“专辑”和“曲目”自定义帖子类型。我希望能够根据专辑分类法对专辑和曲目帖子使用不同的“单张”模板。

基于上面Kaiser的回答,我编写了此代码。效果很好。
注意。我不需要add_action()。 -cpt-album-tax-serendipity.php和WP将自动使用它们; “ tax-serendipity”是第一个“专辑”分类法术语的标语。

作为参考,“ single_template”过滤钩在以下位置声明:

谢谢Kaiser提供示例代码。

干杯,
格雷戈里

评论


嗨,格雷格-欢迎来到WPSE。请仅将答案发布为问题的答案,而不是后续问题。如果您有一个现有答案无法回答的问题,且太大而无法发表评论,请打开另一个问题:)

–斯蒂芬·哈里斯(Stephen Harris)
2012年4月18日在15:07

字符串/数组问题已删除:-)

–格雷戈里
2012年4月18日在16:04

“谢谢Kaiser提供示例代码。” - 别客气。

– kaiser
2012年10月23日下午13:01

对你起作用吗?首先,'$ template'不应在您的代码中被注释..我认为应该以'$ object-> post_name'代替'$ album_tax [0]-> slug',不是吗?

–regregmatys
13年11月18日在14:14

修复了$ template行。谢谢。 $ object-> post_name?没有。那会返回帖子的内容,但是我需要帖子链接到的相册的内容。

–格雷戈里
13年11月18日在23:21



#6 楼

更新Brians代码后,我发现当不使用下拉框时,“默认”模板选项被保存到wp_page_template中,这导致它尝试查找名为default的模板。此更改仅在保存时检查选项“ default”,然后删除帖子元(如果您将模板选项更改为默认值,则很有用)

elseif(MY_CUSTOM_POST_TYPE === $_POST['post_type']) {

if ( esc_attr($_POST['_wp_page_template']) === "default" ) :
    delete_post_meta($post_id, '_wp_page_template');
else :
    update_post_meta($post_id, '_wp_page_template', esc_attr($_POST['_wp_page_template']));
endif;
}