问题描述
在 wordpress 中,我有三种自定义帖子类型:展览、书籍、电影。我有一个包含两个分类术语(store-1 和 store-2)的分类法,可应用于所有 CPT。
我需要实现的是有一个带有永久链接 www.mysite.com/exhibitions 的页面,其中列出了标记为 store-1 和 store-2 的帖子,这可以通过 CPT 轻松完成。但是,我还希望有永久链接,例如 www.mysite.com/exhibitions/store-1,其中列出了所有来自展览 CPT 的 store-1 分类法的帖子(对于每个 CPT 和每个分类法术语,依此类推)。然而,这会在永久链接中混合使用 CPT 和分类术语,我不知道该怎么做。
我的猜测是反转逻辑并创建三个自定义分类法,分别命名为展览、书籍和电影(当然,我需要将 CPT slug 更改为 cpt-exhibitions、cpt-books 和 cpt-movies),并为每个其中创建术语 store-1 和 store-2。通过这种方式,我将获得诸如 www.mysite.com/exhibitions/store-1 之类的永久链接。关于 www.mysite.com/exhibitions 等永久链接,我正在考虑使用该页面的自定义模板创建一个带有 slug“展览”的页面。在模板的 PHP 中,我会添加一个循环来获取所有 cpt-exhibitions 帖子,无论分类术语如何。
这不是一个真正干净的解决方案,因为我在后端基本上有三个空页面,仅用于永久链接目的。所以我想知道:是否有一个特定的功能或重写规则来实现我需要的 CPT 命名展览、书籍、电影和仅适用于所有 CPT 的一个自定义分类法(例如商店)?
感谢您的见解!
解决方法
我曾经有过这样的设置,并通过一些重写规则解决了它。查看此代码,它确实提供了您需要的永久链接,但可能需要您进行一些测试。是的,不要害怕在 WordPress 中重写规则。尽管有些事情可能会付出代价(即性能问题)
add_filter('init','create_movies_taxonomies');
add_filter('init','create_movies_cpt');
add_action('init','movies_rewrite_rules');
add_filter('post_type_link','movies_post_permalinks',10,2);
/**
* First create Stores taxonomy
*/
function create_movies_taxonomies() {
register_taxonomy('stores',['movies'],[
'label' => __('Stores','textdomain'),'public' => true,'show_in_nav_menus' => false,'show_ui' => true,'show_in_menu' => true,'show_tagcloud' => false,'show_in_rest' => true,'hierarchical' => false,'rewrite' => ['slug' => 'store','hierarchical' => false,'with_front' => false],'show_admin_column' => true,'query_var' => true
]
);
}
/**
* Then create Movies CPT with support for Stores and proper rewrites
*/
function create_movies_cpt() {
register_post_type('movies',[
'label' => __('Movies','public' => true,'publicly_queryable' => true,'show_ui' => true,'show_in_menu' => true,'exclude_from_search' => false,'capability_type' => 'post','map_meta_cap' => true,'show_in_rest' => true,'hierarchical' => false,'rewrite' => [
'slug' => '/movies/%stores%','with_front' => false,'feeds' => false
],'query_var' => true,'supports' => ['title','tags','editor','comments','custom-fields','thumbnail'],'has_archive' => 'movies','taxonomies' => ['stores'],'show_in_nav_menus' => true,'menu_icon' => 'dashicons-welcome-learn-more',]
);
}
/**
* Add some rewrite rules for our archives (CPT,taxonomy archive)
*/
function movies_rewrite_rules() {
add_rewrite_rule(
'movies/([a-z]+)/page/?([0-9]{1,})/?$','index.php?post_type=movies&stores=$matches[1]&paged=$matches[2]','top'
);
add_rewrite_rule(
'movies/([a-z]+)/([a-z0-9_-]+)/?$','index.php?post_type=movies&stores=$matches[1]&movies=$matches[2]','top'
);
add_filter('query_vars',function($vars) {
$vars[] .= 'stores';
$vars[] .= 'stores-page';
return $vars;
});
}
/**
* Creates beautiful CPT permalinks,like site.com/movies/%term%/%post%/
*
* @param $permalink
* @param $post
*
* @return string|string[]
*/
function movies_post_permalinks($permalink,$post) {
// if it's not our CPT,return regular permalinks
if (strpos($permalink,'%stores%') === false) {
return $permalink;
}
// Get post taxonomy term
$terms = get_the_terms($post,'stores');
// if a post has a term (store),push it into URL
if ( ! is_wp_error($terms) && ! empty($terms) && is_object($terms[0])) {
$term_slug = array_pop($terms)->slug;
} // if it doesn't,push something there,let it be d
else {
$term_slug = 'd';
}
return str_replace('%stores%',$term_slug,$permalink);
}