我试图创建一个URL结构,如domain.com/term/postname, 但我只得到404对于所有非CPT页面。
function add_video_post_type() {
$labels = array(
\'name\' => _x( \'Videos\', \'Post Type General Name\', \'kibble\' ),
\'singular_name\' => _x( \'Video\', \'Post Type Singular Name\', \'kibble\' ),
\'menu_name\' => __( \'Videos\', \'kibble\' ),
\'parent_item_colon\' => __( \'Parent Item:\', \'kibble\' ),
\'all_items\' => __( \'All Items\', \'kibble\' ),
\'view_item\' => __( \'View Item\', \'kibble\' ),
\'add_new_item\' => __( \'Add New Item\', \'kibble\' ),
\'add_new\' => __( \'Add New\', \'kibble\' ),
\'edit_item\' => __( \'Edit Item\', \'kibble\' ),
\'update_item\' => __( \'Update Item\', \'kibble\' ),
\'search_items\' => __( \'Search Item\', \'kibble\' ),
\'not_found\' => __( \'Not found\', \'kibble\' ),
\'not_found_in_trash\' => __( \'Not found in Trash\', \'kibble\' ),
);
$rewrite = array(
\'slug\' => \'%video_genre%\',
\'with_front\' => true,
\'pages\' => true,
\'feeds\' => true,
);
$args = array(
\'label\' => __( \'video_type\', \'kibble\' ),
\'description\' => __( \'Video Posts\', \'kibble\' ),
\'labels\' => $labels,
\'supports\' => array( \'title\', \'editor\', \'thumbnail\', ),
\'taxonomies\' => array( \'video_genre\' ),
\'hierarchical\' => false,
\'public\' => true,
\'show_ui\' => true,
\'show_in_menu\' => true,
\'show_in_nav_menus\' => true,
\'show_in_admin_bar\' => true,
\'menu_position\' => 5,
\'menu_icon\' => \'dashicons-format-video\',
\'can_export\' => true,
\'has_archive\' => true,
\'exclude_from_search\' => false,
\'publicly_queryable\' => true,
\'rewrite\' => $rewrite,
\'capability_type\' => \'page\',
);
register_post_type( \'video_type\', $args );
}
add_action( \'init\', \'add_video_post_type\', 0 );
function custom_video_genre() {
$labels = array(
\'name\' => _x( \'Video Categories\', \'Taxonomy General Name\', \'kibble\' ),
\'singular_name\' => _x( \'Video Category\', \'Taxonomy Singular Name\', \'kibble\' ),
\'menu_name\' => __( \'Categories\', \'kibble\' ),
\'all_items\' => __( \'All Items\', \'kibble\' ),
\'parent_item\' => __( \'Parent Item\', \'kibble\' ),
\'parent_item_colon\' => __( \'Parent Item:\', \'kibble\' ),
\'new_item_name\' => __( \'New Item Name\', \'kibble\' ),
\'add_new_item\' => __( \'Add New Item\', \'kibble\' ),
\'edit_item\' => __( \'Edit Item\', \'kibble\' ),
\'update_item\' => __( \'Update Item\', \'kibble\' ),
\'separate_items_with_commas\' => __( \'Separate items with commas\', \'kibble\' ),
\'search_items\' => __( \'Search Items\', \'kibble\' ),
\'add_or_remove_items\' => __( \'Add or remove items\', \'kibble\' ),
\'choose_from_most_used\' => __( \'Choose from the most used items\', \'kibble\' ),
\'not_found\' => __( \'Not Found\', \'kibble\' ),
);
$args = array(
\'labels\' => $labels,
\'hierarchical\' => true,
\'public\' => true,
\'show_ui\' => true,
\'show_admin_column\' => true,
\'show_in_nav_menus\' => true,
\'show_tagcloud\' => true,
);
register_taxonomy( \'video_genre\', \'video_type\', $args );
}
add_action( \'init\', \'custom_video_genre\', 0 );
add_filter(\'post_type_link\', \'filter_post_type_link\', 10, 2);
function filter_post_type_link( $link, $post ) {
if ( strpos( $link, \'%video_genre%\' ) === false )
return $link;
$terms = wp_get_object_terms( $post->ID, \'video_genre\' );
if ( current( $terms ) ) :
$new_parent = current( $terms );
foreach ( $terms as $term ) {
if ( $term->parent == 0 ) {
$new_parent = $term;
break;
}
}
$new_parent = $new_parent ? $new_parent : $terms[0];
$category_string = $new_parent->slug;
$category_string = trim( $category_string, \'/\' );
endif;
// set a default
$category_string = ( isset( $category_string ) && $category_string ) ? $category_string : \'uncategorized\';
$link = str_replace( \'%video_genre%\', $category_string, $link );
return $link;
}
SO网友:Bendoh
我的结果就是您所经历的:启用此代码后,普通帖子返回404。如果我禁用了代码,但没有重置永久链接,我就会得到错误的帖子。
上面的答案并不能真正解释发生了什么,所以我释放了我的调试器。
我看到的是,对于普通帖子,它试图设置video_genre
和video_type
解析普通帖子的permalink后查询vars,这是不正确的。
我觉得在重写slug中使用替换变量看起来很奇怪,结果证明我是对的,这就是问题所在。使用这些替换变量可以提供如下永久匹配模式:
%video_genre%/feed/(feed|rdf|rss|rss2|atom)/
=>
$post_type=video_type&feed=$matches[1]
和
([^/]+)/([^/]+)(/[0-9]+)?/?$
=>
index.php?video_genre=$matches[1]&video_type=$matches[2]&page=$matches[3]
这是与我对常规帖子的请求相匹配的规则,因此设置video\\u流派和video\\u类型查询变量,而不是实际生成帖子的正确变量。
因此,虽然substitution变量在创建链接时很有用,但在filter_post_type_link
, 它打破了permalink匹配系统。
解决方案
您尝试执行的操作会在永久链接结构中产生继承冲突,因为WordPress不知道您是尝试访问video\\u类型的CPT还是常规帖子。
相反,我要做的是设置rewrite
参数到false
您可以在其中调用register\\u post\\u type。然后在你的post_type_link
筛选,根据要筛选的帖子类型显式返回链接video_type
而不是依赖于您使用的替换变量。
function filter_post_type_link( $link, $post ) {
if( $post->post_type != \'video_type\' )
return $link;
$terms = wp_get_object_terms( $post->ID, \'video_genre\' );
if ( current( $terms ) ) :
$new_parent = current( $terms );
foreach ( $terms as $term ) {
if ( $term->parent == 0 ) {
$new_parent = $term;
break;
}
}
$new_parent = $new_parent ? $new_parent : $terms[0];
$category_string = $new_parent->slug;
$category_string = trim( $category_string, \'/\' );
endif;
// set a default
$category_string = ( isset( $category_string ) && $category_string ) ? $category_string : \'uncategorized\';
$link = home_url( path_join( $category_string, $post->post_name ) );
return $link;
}
然后手动解析请求并设置所需的变量:
function wpse135707_parse_request( $wp ) {
$terms = get_terms( \'video_genre\', array( \'hide_empty\' => false, \'fields\' => \'id=>slug\' ) );
if( preg_match( \'#^(\' . join( \'|\', $terms ) . \')/([^/]+)#\', $wp->request, $matches ) ) {
$wp->query_vars = array(
\'post_type\' => \'video_type\',
\'name\' => $matches[2]
);
}
}
add_action( \'parse_request\', \'wpse135707_parse_request\' );
然而,这种方法有一个缺点,即可能与其他permalinks发生冲突。这将解析任何以任何video\\u流派slug开头的URL,并假设它是video\\u类型的帖子,这可能适合您的目的。