我的网站有两种自定义的帖子类型和两种分类法。一种分类法是“位置”,分为两级/层级(国家、城市)。我的目标是获得我们的职位类型;SEO中的分类法相当Permalink结构。我已经完成了Permalink的大部分结构,但我仍然在Post/Slug登录页上看到404的错误。我已经走到一半了,我已经失去了耐心,我尝试了几十种解决方案,它们似乎都打破了这一点或那一点。
Post Types: 远足、潜水
Taxonomies: 位置、游览类别
Taxonomy Pages:
工作地点/地点/%地点国家%/
工作-/地点/%地点国家%/%地点城市%/
Post Type Pages:
工作/停留潜水/%地点国家%/
工作/停留潜水/%地点国家%/%地点城市%/
不工作/保持潜水/%位置国家%/%位置城市%/Slug-不工作
工作/旅行/%地点国家%/
不工作-/旅行/%地点国家%/%地点城市%/
不工作-/短途旅行/%地点国家%/%地点城市%/Slug
工作/出差/%出差类别%/
不工作-/游览/%游览类别%/%地点国家%/
不工作-/远足/%远足类别%/%地点国家%/%地点城市%/
Taxonomy Code:
// excursion category
register_taxonomy(\'pdm_excursion_category\', array(\'pdm_excursion\'), array(
\'labels\' => array(
\'name\' => _x(\'Categories\', \'taxonomy general name\', \'pdm\'),
\'singular_name\' => _x(\'Category\', \'taxonomy singular name\', \'pdm\'),
\'menu_name\' => __(\'Categories\', \'pdm\'),
\'all_items\' => __(\'All Categories\', \'pdm\'),
\'edit_item\' => __(\'Edit Category\', \'pdm\'),
\'view_item\' => __(\'View Category\', \'pdm\'),
\'update_item\' => __(\'Update Category\', \'pdm\'),
\'add_new_item\' => __(\'Add New Category\', \'pdm\'),
\'new_item_name\' => __(\'New Category Name\', \'pdm\'),
\'parent_item\' => __(\'Parent Category\', \'pdm\'),
\'parent_item_colon\' => __(\'Parent Category:\', \'pdm\'),
\'search_items\' => __(\'Search Categories\', \'pdm\'),
\'popular_items\' => __(\'Popular Categories\', \'pdm\'),
\'separate_items_with_commas\' => __(\'Separate categories with commas\', \'pdm\'),
\'add_or_remove_items\' => __(\'Add or remove categories\', \'pdm\'),
\'choose_from_most_used\' => __(\'Choose from the most used categories\', \'pdm\'),
\'not_found\' => __(\'No categories found.\', \'pdm\'),
),
\'show_ui\' => true,
\'show_admin_column\' => true,
\'hierarchical\' => true,
\'query_var\' => true,
\'rewrite\' => array(\'slug\' => \'excursions\', \'with_front\' => true, \'hierarchical\' => false),
));
// location
register_taxonomy(\'pdm_location\', array(\'pdm_hotel\', \'pdm_excursion\', \'pdm_dive_site\'), array(
\'labels\' => array(
\'name\' => _x(\'Locations\', \'taxonomy general name\', \'pdm\'),
\'singular_name\' => _x(\'Location\', \'taxonomy singular name\', \'pdm\'),
\'menu_name\' => __(\'Locations\', \'pdm\'),
\'all_items\' => __(\'All Locations\', \'pdm\'),
\'edit_item\' => __(\'Edit Location\', \'pdm\'),
\'view_item\' => __(\'View Location\', \'pdm\'),
\'update_item\' => __(\'Update Location\', \'pdm\'),
\'add_new_item\' => __(\'Add New Location\', \'pdm\'),
\'new_item_name\' => __(\'New Location Name\', \'pdm\'),
\'parent_item\' => __(\'Parent Location\', \'pdm\'),
\'parent_item_colon\' => __(\'Parent Location:\', \'pdm\'),
\'search_items\' => __(\'Search Locations\', \'pdm\'),
\'popular_items\' => __(\'Popular Locations\', \'pdm\'),
\'separate_items_with_commas\' => __(\'Separate locations with commas\', \'pdm\'),
\'add_or_remove_items\' => __(\'Add or remove locations\', \'pdm\'),
\'choose_from_most_used\' => __(\'Choose from the most used locations\', \'pdm\'),
\'not_found\' => __(\'No locations found.\', \'pdm\'),
),
\'show_ui\' => true,
\'show_admin_column\' => true,
\'hierarchical\' => true,
\'query_var\' => true,
\'rewrite\' => array(\'slug\' => \'location\', \'with_front\' => false, \'hierarchical\' => true),
));
Post Type Code:
// hotel
register_post_type(\'pdm_hotel\' , array(
\'labels\' => array(
\'name\' => _x(\'Stay & Dive Hotels\', \'post type general name\', \'pdm\'),
\'singular_name\' => _x(\'Stay & Dive\', \'post type singular name\', \'pdm\'),
\'menu_name\' => _x(\'Stay & Dive Hotels\', \'admin menu\', \'pdm\'),
\'name_admin_bar\' => _x(\'Stay & Dive Hotel\', \'add new on admin bar\', \'pdm\'),
\'add_new\' => _x(\'Add New\', \'book\', \'pdm\'),
\'add_new_item\' => __(\'Add New Hotel\', \'pdm\'),
\'new_item\' => __(\'New Stay & Dive Hotel\', \'pdm\'),
\'edit_item\' => __(\'Edit Stay & Dive Hotel\', \'pdm\'),
\'view_item\' => __(\'View Stay & Dive Hotel\', \'pdm\'),
\'all_items\' => __(\'All Stay & Dive Hotels\', \'pdm\'),
\'search_items\' => __(\'Search Stay & Dive Hotels\', \'pdm\'),
\'parent_item_colon\' => __(\'Parent Stay & Dive Hotel:\', \'pdm\'),
\'not_found\' => __(\'No hotels found.\', \'pdm\'),
\'not_found_in_trash\' => __(\'No hotels found in Trash.\', \'pdm\'),
),
\'public\' => true,
\'publicly_queryable\' => true,
\'show_ui\' => true,
\'show_in_menu\' => true,
\'query_var\' => true,
\'rewrite\' => array(\'slug\' => \'stay-dive/%pdm_location%/%pdm_location2%\', \'with_front\' => true),
\'capability_type\' => \'post\',
\'has_archive\' => true,
\'hierarchical\' => false,
\'menu_position\' => 101,
\'menu_icon\' => \'dashicons-admin-home\',
\'supports\' => array(\'title\',\'editor\',\'thumbnail\'),
\'taxonomies\' => array(\'pdm_location\'),
));
// excursions
register_post_type(\'pdm_excursion\' , array(
\'labels\' => array(
\'name\' => _x(\'Excursions\', \'post type general name\', \'pdm\'),
\'singular_name\' => _x(\'Excursion\', \'post type singular name\', \'pdm\'),
\'menu_name\' => _x(\'Excursions\', \'admin menu\', \'pdm\'),
\'name_admin_bar\' => _x(\'Excursion\', \'add new on admin bar\', \'pdm\'),
\'add_new\' => _x(\'Add New\', \'book\', \'pdm\'),
\'add_new_item\' => __(\'Add New Excursion\', \'pdm\'),
\'new_item\' => __(\'New Excursion\', \'pdm\'),
\'edit_item\' => __(\'Edit Excursion\', \'pdm\'),
\'view_item\' => __(\'View Excursion\', \'pdm\'),
\'all_items\' => __(\'All Excursions\', \'pdm\'),
\'search_items\' => __(\'Search Excursions\', \'pdm\'),
\'parent_item_colon\' => __(\'Parent Excursion:\', \'pdm\'),
\'not_found\' => __(\'No excursions found.\', \'pdm\'),
\'not_found_in_trash\' => __(\'No excursions found in Trash.\', \'pdm\'),
),
\'public\' => true,
\'publicly_queryable\' => true,
\'show_ui\' => true,
\'show_in_menu\' => true,
\'query_var\' => true,
\'rewrite\' => array(\'slug\' => \'excursion /%pdm_excursion_category%/%pdm_location%/%pdm_location2%\',\'with_front\' => true),
\'capability_type\' => \'post\',
\'has_archive\' => true,
\'hierarchical\' => false,
\'menu_position\' => 102,
\'menu_icon\' => \'dashicons-location\',
\'supports\' => array(\'title\',\'editor\',\'thumbnail\'),
\'taxonomies\' => array(\'pdm_location\',\'pdm_excursion_category\'),
));
最合适的回答,由SO网友:Enkode 整理而成
找到具有以下解决方案的git repo:https://github.com/hemal21/WordPress-CPT-Hierarchical-Taxonomy-Permalinks/blob/master/cpt-hierarchical-tax-permalinks.php
我需要进行重写,下面是一个使用permalink代码的示例:
<?php
/**
* WordPress Custom Post Type and Hierarchical Taxonomy Permalinks
*
* Ever wanted to have custom taxonomy permalinks that reflect parent/child relation?
* Then this is for you. Still in development though.
*
* @version 1.0b
* @author Kenth Hagström
* @link http://www.facebook.com/keha76
* @license GNU General Public License v2
*
* Last updated 19 sep 2013, 15:30(GMT+1)
*
* KNOWN BUGS:
* - When a \'photo\' is published without any taxonomy, the URL url.tld/photos/john does not work.
* - The full URL url.tld/photos/family/kids/john/ has an unwanted trailing slash.
*
* These URL structures work:
* url.tld/photos/ loads archive-photo.php
* url.tld/photos/family/ loads taxonomy-album.php
* url.tld/photos/family/kids/ loads taxonomy-album.php
* url.tld/photos/family/kids/john loads single-photo.php
* url.tld/photos/page/2 loads page 2 with archive-photo.php
*
* If you try this code, remember to flush your permalinks. Go to \'settings->permalinks\' and it\'s done.
*
**/
function keha_register_photo_tax_album() {
$labels = array(
\'name\' => _x( \'Albums\', \'taxonomy general name\', \'blank\' ),
\'singular_name\' => _x( \'Album\', \'taxonomy singular name\', \'blank\' ),
\'search_items\' => __( \'Search Albums\', \'blank\' ),
\'all_items\' => __( \'All Albums\', \'blank\' ),
\'parent_item\' => __( \'Parent Album\', \'blank\' ),
\'parent_item_colon\' => __( \'Parent Album:\', \'blank\' ),
\'edit_item\' => __( \'Edit Album\', \'blank\' ),
\'update_item\' => __( \'Update Album\', \'blank\' ),
\'add_new_item\' => __( \'Add New Album\', \'blank\' ),
\'new_item_name\' => __( \'New Album Name\', \'blank\' ),
\'menu_name\' => __( \'Albums\', \'blank\' ),
);
$rewrite = array(
\'slug\' => \'album\',
\'with_front\' => false,
\'hierarchical\' => true
);
$args = array(
\'hierarchical\' => true,
\'labels\' => $labels,
\'show_ui\' => true,
\'query_var\' => true,
\'rewrite\' => $rewrite
);
register_taxonomy( \'album\', array( \'photo\' ), $args );
}
add_action( \'init\', \'keha_register_photo_tax_album\' );
function keha_register_cpt_photo() {
$labels = array(
\'name\' => __( \'Photos\', \'blank\' ),
\'singular_name\' => _x( \'Photo\', \'Photo post type singular\', \'blank\' ),
\'add_new\' => __( \'Add New\', \'blank\' ),
\'add_new_item\' => __( \'Add New Photo\', \'blank\' ),
\'edit_item\' => __( \'Edit Photo\', \'blank\' ),
\'new_item\' => __( \'New Photo\', \'blank\' ),
\'all_items\' => __( \'All Photos\', \'blank\' ),
\'view_item\' => __( \'View Photo\', \'blank\' ),
\'search_items\' => __( \'Search Photos\', \'blank\' ),
\'not_found\' => __( \'No photos found\', \'blank\' ),
\'not_found_in_trash\' => __( \'No photos found in Trash\', \'blank\' ),
\'parent_item_colon\' => \'\',
\'menu_name\' => __( \'Photos\', \'blank\' )
);
$rewrite = array(
\'slug\' => \'photos\',
\'hierarchical\' => true,
\'with_front\' => true
);
$args = array(
\'labels\' => $labels,
\'exclude_from_search\' => false,
\'publicly_queryable\' => true,
\'show_ui\' => true,
\'show_in_nav_menus\' => true,
\'show_in_menu\' => true,
\'show_in_admin_bar\' => true,
\'menu_position\' => 20,
\'menu_icon\' => null, // Handled from CSS
\'capability_type\' => \'post\',
\'hierarchical\' => false,
\'public\' => true,
\'supports\' => array( \'title\', \'editor\', \'thumbnail\' ),
\'taxonomies\' => array( \'album\' ),
\'rewrite\' => $rewrite,
\'has_archive\' => true,
\'query_var\' => true,
\'can_export\' => true
);
register_post_type( \'photo\', $args );
}
add_action( \'init\', \'keha_register_cpt_photo\' );
function keha_add_rewrite_rules() {
add_rewrite_rule( \'^photos/(.+?)/(.+?)/(.+?)$\', \'index.php?album=$matches[1]&album=$matches[2]&photo=$matches[3]\', \'top\' );
add_rewrite_rule( \'^photos/(.+?)/(.+?)/$\', \'index.php?photo=$matches[2]\', \'top\' );
add_rewrite_rule( \'^photos/(.+?)/(.+?)/(.+?)$\', \'index.php?photo=$matches[3]\', \'top\' );
add_rewrite_rule( \'^photos/(.+?)/(.+?)/?$\', \'index.php?album=$matches[2]\', \'top\' );
add_rewrite_rule( \'^photos/(.+?)$\', \'index.php?album=$matches[1]\', \'top\' );
}
add_action(\'init\', \'keha_add_rewrite_rules\');
function keha_post_type_link( $post_link, $post, $leavename ) {
global $wp_rewrite;
$draft_or_pending = isset( $post->post_status ) && in_array( $post->post_status, array( \'draft\', \'pending\', \'auto-draft\' ) );
if ( $draft_or_pending and !$leavename ) {
return $post_link;
}
if ( $post->post_type == \'photo\' ) {
$post_type_object = get_post_type_object( $post->post_type );
$post_link = home_url() . \'/\' . $post_type_object->rewrite[\'slug\'] . \'/\';
$parent_dirs = \'\';
if ( $terms = get_the_terms( $post->ID, \'album\' ) ) {
foreach ( $terms as $term ) {
if ( $term->parent != 0 ) {
$dirs = keha_get_taxonomy_parents( $term->term_id, \'album\', false, \'/\', true );
} else {
$dirs = $term->slug.\'/\';
}
}
}
$post_link = $post_link . $dirs . $post->post_name;
}
return $post_link;
}
add_filter( \'post_type_link\', \'keha_post_type_link\', 10, 3 );
/**
* Custom function based on WordPress own get_category_parents()
* @link http://core.trac.wordpress.org/browser/tags/3.6.1/wp-includes/category-template.php#L0
*
* @param integer $id
* @param string $taxonomy
* @param string $link
* @param string $separator
* @param string $nicename
* @param array $visited
* @return string
*/
function keha_get_taxonomy_parents( $id, $taxonomy = \'category\', $link = false, $separator = \'/\', $nicename = false, $visited = array() ) {
$chain = \'\';
$parent = get_term( $id, $taxonomy, OBJECT, \'raw\');
if ( is_wp_error( $parent ) ) {
return $parent;
}
if ( $nicename ){
$name = $parent->slug;
} else {
$name = $parent->name;
}
if ( $parent->parent && ( $parent->parent != $parent->term_id ) && !in_array( $parent->parent, $visited ) ) {
$visited[] = $parent->parent;
$chain .= keha_get_taxonomy_parents( $parent->parent, $taxonomy, $link, $separator, $nicename, $visited );
}
if ( $link ) {
$chain .= \'<a href="\' . get_term_link( $parent->term_id, $taxonomy ) . \'" title="\' . esc_attr( sprintf( __( "View all posts in %s" ), $parent->name ) ) . \'">\'.$name.\'</a>\' . $separator;
}else {
$chain .= $name.$separator;
}
return $chain;
}