自定义分类,带自定义重写/插件,并从插件加载分类归档模板

时间:2021-05-26 作者:rugbert

我想也许我对自定义分类法和CPT的重写和模板的理解是错误的,也许这里的人可以帮助我解决问题并教育我。

因此,我有一个帖子类型“post type”;wiki文档;和一个职位类型;wiki新闻;。每个都设置了自定义段塞:

wiki文档的重写设置为:

\'rewrite\' => [
    \'slug\' => \'wiki/documentation\',
],
wiki新闻的“重写”设置为:

\'rewrite\' => [
    \'slug\' => \'wiki/news\',
],
这也是我所期望的。mysite.com/wiki/documentation 加载存档模板和模板条件is_archive() wiki文档帖子类型。

但是,我还有一个自定义分类法,叫做wiki-help-topic 其中重写了:

\'rewrite\' => [
    \'slug\' => \'wiki/help-topics\',
],
然而,这个弹头不起作用。mysite.com/wiki/help-topics 抛出404。mysite.com/wiki/help-topics/term-whatever 但确实有效,并且模板是有条件的is_tax() 这就是我想要的。

我尝试添加此重写规则:

    add_rewrite_rule(
        \'^wiki/help-topics?$\',
        \'index.php?taxonomy=wiki-help-topic\',
        \'top\',
    );
但现在页面加载is_home() 这很奇怪。

所以这是第一个问题。

第二个相关问题是,我还希望一些自定义重写来显示所有wiki-doc 贴有wiki-help-topic 术语,但我希望它使用分类法归档(有条件is_tax())

我的规则一直使用is_archive() 有条件的,因此是存档模板,例如:

add_rewrite_rule(
  \'^wiki/documentation/help-topic/([^/]+)?$\',
  \'index.php?post_type=wiki-doc&wiki-help-topic=$matches[1]\',
  \'top\',
);
这将加载所有wiki-doc 标记为的帖子wiki-help-topic 但它使用的是归档模板,而不是分类模板。

是否可以使用此URLis_tax() 而是让我可以为该分类法或分类法术语使用特定的模板文件?

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

背景(&A);核心功能为什么一个分类路径Slug单独产生一个404,但是这个Slug不起作用。我的网站。com/wiki/help主题抛出404。

WordPress不提供;分类术语档案”;开箱即用—即模板层次结构和WP_Query/WP_Tax_Query 逻辑支持在分类法中直接显示术语,而两者都是为了将请求路由到post 所容纳之物我认为省略此行为的决定是合理的,因为在请求一种分类法时,可能希望显示的内容在不同的用例之间有很大的差异。

在普通安装中,通过尝试访问地址,这一点很明显/index.php?taxonomy=category/category 假设一个相当永久的结构(我将假设/%category%/%postname%/ 此响应其余部分的配置)。

由于该机制不存在,WordPress不会为基生成重写规则/category URL(访问该路径不会生成查询index.php?taxonomy=category) 因此URL路径处理依赖于更多的全局规则/category 最终被解释为它是一个页面slug,并且-假设您没有创建带有slug的页面category - WordPress生成404响应,因为不存在这样的页面。

mysite.com/wiki/help-topics/term-whatever 但确实有效,模板条件为is\\u tax(),这正是我想要的。

通过提供URL路径现在正确映射到为分类法注册生成的重写规则中的术语,WordPress能够使用完整的WP_Tax_Query 要检索的子句posts

为什么一个分类查询变量单独生成主页/首页

我尝试添加这个重写规则:[…]但现在加载的页面是\\u home(),这很奇怪。

正如WordPress不会为孤立的分类法段塞构建路由一样,在将查询参数解析为查询/查询变量时,WP_Query 使用以下逻辑构建WP_Tax_Query:

if ( ! empty( $q[\'taxonomy\'] ) && ! empty( $q[\'term\'] ) ) {
  $tax_query[] = array(
    \'taxonomy\' => $q[\'taxonomy\'],
    \'terms\'    => array( $q[\'term\'] ),
    \'field\'    => \'slug\',
  );
}
因此,自/index.php?taxonomy=wiki-help-topic 不包括分类术语,它在主查询的组合中被完全忽略,空查询生成主页。

模板层次结构选择优先级第二个相关问题是,我还希望进行一些自定义重写,以显示标记有wiki帮助主题术语的所有wiki文档帖子的列表,但我希望它使用分类法存档(有条件的is\\u tax())

由参数组成的查询?wiki-help-topic=some-topic&post_type=wiki-doc 应生成$wp_query 反映两者is_tax() 以及is_post_type_archive()is_archive() - 事实上,如果查询is_tax()is_post_type_archive() 它是隐含的is_archive()

你可以看到the code in WP_Query which determines these properties 在这里

与直觉相反,它看起来像the code determining which object is considered "the main queried object" 使分类法优先于post类型,但the code which determines which template hierarchy entry point to load 使post类型存档模板优先于分类法模板。。。

我真的不确定这是否是一个bug,或者加载的模板是否经常与查询的对象不一致。

解决方案

将分类法根请求路由到分类法中的所有帖子

有几种不同的方法来处理此问题,但我认为最有用的方法是将针对没有术语的分类法的请求转换为针对分类法中每个术语的请求:

/**
 * Transforms incoming queries specifying a taxonomy slug but no terms into a
 * query targeting all terms within that taxonomy. Note that this handles the
 * specific case of the "taxonomy" query variable being set and the "term"
 * query variable unset - it does not address the case of a taxonomy-specific
 * query variable being present but empty.
 * 
 * @param WP $wp The WP class instance representing the current request.
 **/
function wpse388742_parse_taxonomy_root_request( $wp ) {
  $tax_name      = $wp->query_vars[\'taxonomy\'];

  // Bail out if no taxonomy QV was present, or if the term QV is.
  if( empty( $tax_name ) || isset( $wp->query_vars[\'term\'] ) )
    return;
  
  $tax           = get_taxonomy( $tax_name );
  $tax_query_var = $tax->query_var;

  // Bail out if a tax-specific qv for the specific taxonomy is present.
  if( isset( $wp->query_vars[ $tax_query_var ] ) )
    return;
  
  $tax_term_slugs = get_terms(
    [
      \'taxonomy\' => $tax_name,
      \'fields\'   => \'slugs\'
    ]
  );

  // Unlike "taxonomy"/"term" QVs, tax-specific QVs can specify an AND/OR list of terms.
  $wp->set_query_var( $tax_query_var, implode( \',\', $tax_term_slugs ) );
}

add_action( \'parse_request\', \'wpse388742_parse_taxonomy_root_request\' );
尽早执行此转换可以让WordPress像往常一样设置其余的请求和查询,这意味着WP_Query 对象将适当反映is_tax(), is_post_type_archive(), 和is_archive() 没有任何进一步的工作。

然后,您可以像在问题中所做的那样,使用重写规则显式地将请求路由到分类法slug,或者可以使用registered_taxonomy 用于公开所有可公开查询的分类的行为的操作挂钩:

/**
 * Rewrite requests for the isolated slug of publicly queryable taxonomies to
 * a request specifying the taxonomy without specifying any terms.
 *
 * @param string   $name The name of the registered taxonomy.
 * @param string[] $types An array of object type names which the taxonomy is associated with.
 * @param Array    $tax The WP_Taxonomy object, cast to an associative array.
 **/
function wpse388742_register_tax_root_rewrite( $name, $types, $tax ) {
  if( empty( $tax[\'publicly_queryable\'] ) )
    return;

  $slug = empty( $tax[\'rewrite\'] ) || empty( $tax[\'rewrite\'][\'slug\'] ) ? $name :  $tax[\'rewrite\'][\'slug\'];

  add_rewrite_rule( "^$slug/?$", "index.php?taxonomy=$name", \'top\' );
}

add_action( \'registered_taxonomy\', \'wpse388742_register_tax_root_rewrite\', 10, 3 );

模板优先级

我们可以使用template_include 筛选钩子以在这些特定条件下使用分类法归档模板-我认为这应该可以工作,假设分类法术语确实是查询的对象(get_taxonomy_template() 取决于它是如何构造正确的上下文模板文件路径):

function wpse388741_doc_help_topic_template( $template ) {
  if( is_tax( \'wiki-help-topic\' ) && is_post_type_archive( \'wiki-doc\' ) )
    return get_taxonomy_template();

  return $template;
}

add_filter( \'template_include\', \'wpse388741_doc_help_topic_template\' );
该查询由?wiki-help-topic=some-topic&post_type=wiki-doc 应使用分类法存档模板,而不是post类型存档模板。

通过从is_ 条件。

相关推荐

Updating modified templates

我想调整一些。php模板文件在我的WordPress主题中,我知道正确的过程是将相关文件复制到子主题文件夹中并在那里编辑文件,这样我的修改就不会在将来的主题更新中丢失。但这是否意味着我将无法从主题更新中获益,因为我将文件放在了我的子主题文件夹中?这可能不是一件好事,因为主题更新可能添加了一些有用的特性,甚至修复了我最初需要对代码进行调整的问题!这方面的常见解决方案是什么?有人推荐了一款Diff应用程序——这是人们常用的吗?