自定义帖子类型和分类URL结构

时间:2018-02-13 作者:J Robz

我有一个自定义的帖子类型products 和一个带有slug的自定义分类“产品类别”products.

My goal: 我正在尝试创建如下URL结构:

产品发布类型存档:products/

产品顶级类别存档:products/product-category

产品类别档案:products/product-category/product-sub-category

产品页面:products/product-category/product-sub-category/product-page

The problem:产品页面似乎只想使用实际类别。所以URL结构看起来像products/uncategorized/product-page. 类别存档页不会维护cpt库。所以他们的结果是category/sub-category.

What I\'ve tried: 无数的谷歌搜索,相当多的代码片段(我记得我将在下面介绍)、一些自定义函数和一些插件。没有用。

我有以下代码。

add_action( \'init\', \'products_cpt\', 0);
add_action( \'init\', \'register_taxonomies\', 0 );

//A custom post type for all products
function products_cpt(){
    $labels = array(
        \'name\'               => _x(\'Products\', \'Post Type General Name\'),
        \'singular_name\'      => _x(\'Product\', \'Post Type Singluar Name\'),
        \'menu_name\'          => __(\'Products\'),
        \'parent_item_colon\'  => __(\'Parent Product\'),
        \'all_items\'          => __(\'All Products\'),
        \'view_item\'          => __(\'View Product\'),
        \'add_new_item\'       => __(\'Add New Product\'),
        \'add_new\'            => __(\'Add New\'),
        \'edit_item\'          => __(\'Edit Product\'),
        \'update_item\'        => __(\'Update Product\'),
        \'search_items\'       => __(\'Search Products\'),
        \'not_found\'          => __(\'Not Found\'),
        \'not_found_in_trash\' => __(\'Not Found in Trash\')
    );
    $supports = array( 
        \'title\', 
        \'editor\', 
        \'excerpt\', 
        \'thumbnail\', 
        \'custom-fields\', 
        \'revisions\' 
    );
    $args = array(
        \'labels\'              => $labels,
        \'hierarchical\'        => true,
        \'public\'              => true,
        \'exclude_from_search\' => false,
        \'show_in_admin_bar\'   => true,
        \'show_in_nav_menus\'   => true,
        \'publicly_queryable\'  => true,
        \'query_var\'           => true,
        \'taxonomies\'          => array( \'chemicals\' ),
        \'supports\'            => $supports,
        \'has_archive\'         => \'products\'
    );
    register_post_type(\'products\', $args);
}

function register_taxonomies() {
    $taxonomies = array(
        \'products\' => array(
            \'Product\',
            \'Products\'
        ),
    );
    foreach($taxonomies as $slug => $name){
        create_product_taxonomy($slug,$name[0],$name[1]);
    }
}

function create_product_taxonomy($slug, $singular, $plural) {
    $labels = array(
        \'name\'                       => _x( $singular.\' Categories\', \'Taxonomy General Name\', \'text_domain\' ),
        \'singular_name\'              => _x( $singular.\' Category\', \'Taxonomy Singular Name\', \'text_domain\' ),
        \'menu_name\'                  => __( $singular.\' Categories\', \'text_domain\' ),
        \'all_items\'                  => __( \'All \'.$singular.\' Categories\', \'text_domain\' ),
        \'parent_item\'                => __( \'Parent \'.$singular.\' Category\', \'text_domain\' ),
        \'parent_item_colon\'          => __( \'Parent \'.$singular.\' Category:\', \'text_domain\' ),
        \'new_item_name\'              => __( \'New \'.$singular.\' Category Name\', \'text_domain\' ),
        \'add_new_item\'               => __( \'Add New \'.$singular.\' Category\', \'text_domain\' ),
        \'edit_item\'                  => __( \'Edit \'.$singular.\' Category\', \'text_domain\' ),
        \'update_item\'                => __( \'Update \'.$singular.\' Category\', \'text_domain\' ),
        \'view_item\'                  => __( \'View \'.$singular.\' Category\', \'text_domain\' ),
        \'separate_items_with_commas\' => __( \'Separate \'.$singular.\' Categories with commas\', \'text_domain\' ),
        \'add_or_remove_items\'        => __( \'Add or remove \'.$singular.\' Categories\', \'text_domain\' ),
        \'choose_from_most_used\'      => __( \'Choose from the most used \'.$singular.\' Categories\', \'text_domain\' ),
        \'popular_items\'              => __( \'Popular \'.$singular.\' Categories\', \'text_domain\' ),
        \'search_items\'               => __( \'Search \'.$singular.\' Categories\', \'text_domain\' ),
        \'not_found\'                  => __( \'Not Found\', \'text_domain\' ),
        \'no_terms\'                   => __( \'No \'.$singular.\' Categories\', \'text_domain\' ),
        \'items_list\'                 => __( $singular.\' Categories list\', \'text_domain\' ),
        \'items_list_navigation\'      => __( $singular.\' Categories list navigation\', \'text_domain\' ),
    );
     $args = array(
        \'labels\'                     => $labels,
        \'hierarchical\'               => true,
        \'public\'                     => true,
        \'show_ui\'                    => true,
        \'show_admin_column\'          => true,
        \'show_in_nav_menus\'          => true,
        \'show_tagcloud\'              => true,
        \'has_archive\'                => $plural,
        \'rewrite\' => array( 
            \'slug\'         => \'products\',
            \'with_front\'   => true,
            \'hierarchical\' => true
        )
    );
    register_taxonomy( $slug, \'products\', $args );
}
首先,我将永久链接设置设置为:Permalink Settings

接下来,我尝试添加以下代码,但它只适用于产品页面。产品类别档案仍为404\'d。

add_filter( \'post_type_link\', \'products_post_link\', 1, 3 );
function products_post_link( $post_link, $id = 0 ){
    $post = get_post($id);  
    if ( is_object( $post ) ){
        $terms = wp_get_object_terms( $post->ID, \'products_category\' );
        $slug_url = \'\';
        $last_id = 0;
        if( $terms ){
            foreach($terms as $term) {
                if ($term === reset($terms)){
                    foreach($terms as $termInner){
                        if($termInner->term_id == 0){
                            $slug_url .= $termInner->slug.\'/\';
                        }
                    }
                }elseif ($term === end($terms)){
                    foreach($terms as $termInner){
                        if($termInner->parent == $last_id){
                            $slug_url .= $termInner->slug;
                            $last_id = $termInner->term_id;
                        }
                    }
                }else{
                    foreach($terms as $termInner){
                        if($termInner->parent == $last_id){
                            $slug_url .= $termInner->slug.\'/\';
                            $last_id = $termInner->term_id;
                        }
                    }
                }
            }
            return str_replace( \'%category%\' , $slug_url , $post_link );
        }
    }
    return $post_link;  
}
这是CPT init函数的一部分:

    \'rewrite\' => array(
        \'slug\'         => \'products/%category%\',
        \'with_front\'   => false,
        \'hierarchical\' => true,
    ),
我还尝试了以下方法,不记得发生了什么,但我记得它不起作用:

add_action(\'init\', \'custom_resource_rewrite_rules\');
function custom_resource_rewrite_rules() {
    add_rewrite_rule(\'products/([A-Za-z0-9\\-\\_]+)/?\', \'$matches[1]\', \'top\');
}
我还试着玩term_link 滤器没有bueno。

最后,我尝试了以下插件,也没有成功。

Custom Permalinks

Permalinks Customizer

Custom Post Type Permalinks

有人能解决这个问题吗?我在拔头发。

2 个回复
最合适的回答,由SO网友:J Robz 整理而成

永远之后,我找到了答案!

第一:我们注册自定义帖子类型;自定义分类法:

add_action( \'init\', \'register_sps_products_post_type\' );
function register_sps_products_post_type() {
    register_post_type( \'sps-product\',
        array(
            \'labels\' => array(
                \'name\' => \'Products\',
                \'menu_name\' => \'Product Manager\',
                \'singular_name\' => \'Product\',
                \'all_items\' => \'All Products\'
            ),
            \'public\' => true,
            \'publicly_queryable\' => true,
            \'show_ui\' => true,
            \'show_in_menu\' => true,
            \'show_in_nav_menus\' => true,
            \'supports\' => array( \'title\', \'editor\', \'author\', \'thumbnail\', \'comments\', \'post-formats\', \'revisions\' ),
            \'hierarchical\' => false,
            \'has_archive\' => \'products\',
            \'taxonomies\' => array(\'product-category\'),
            \'rewrite\' => array( \'slug\' => \'products/%product_category%\', \'hierarchical\' => true, \'with_front\' => false )
        )
    );
    register_taxonomy( \'product-category\', array( \'sps-product\' ),
        array(
            \'labels\' => array(
                \'name\' => \'Product Categories\',
                \'menu_name\' => \'Product Categories\',
                \'singular_name\' => \'Product Category\',
                \'all_items\' => \'All Categories\'
            ),
            \'public\' => true,
            \'hierarchical\' => true,
            \'show_ui\' => true,
            \'rewrite\' => array( \'slug\' => \'products\', \'hierarchical\' => true, \'with_front\' => false ),
        )
    );
}
接下来,我们添加了一个新的重写规则,以便Wordpress知道如何解释新的permalink结构:

add_action( \'generate_rewrite_rules\', \'register_product_rewrite_rules\' );
function register_product_rewrite_rules( $wp_rewrite ) {
    $new_rules = array( 
        \'products/([^/]+)/?$\' => \'index.php?product-category=\' . $wp_rewrite->preg_index( 1 ), // \'products/any-character/\'
        \'products/([^/]+)/([^/]+)/?$\' => \'index.php?post_type=sps-product&product-category=\' . $wp_rewrite->preg_index( 1 ) . \'&sps-product=\' . $wp_rewrite->preg_index( 2 ), // \'products/any-character/post-slug/\'
        \'products/([^/]+)/([^/]+)/page/(\\d{1,})/?$\' => \'index.php?post_type=sps-product&product-category=\' . $wp_rewrite->preg_index( 1 ) . \'&paged=\' . $wp_rewrite->preg_index( 3 ), // match paginated results for a sub-category archive
        \'products/([^/]+)/([^/]+)/([^/]+)/?$\' => \'index.php?post_type=sps-product&product-category=\' . $wp_rewrite->preg_index( 2 ) . \'&sps-product=\' . $wp_rewrite->preg_index( 3 ), // \'products/any-character/sub-category/post-slug/\'
        \'products/([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$\' => \'index.php?post_type=sps-product&product-category=\' . $wp_rewrite->preg_index( 3 ) . \'&sps-product=\' . $wp_rewrite->preg_index( 4 ), // \'products/any-character/sub-category/sub-sub-category/post-slug/\'
    );
    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}
另一方面,下一个函数修复了子类别的问题。问题本身在于,当您尝试加载URL为faq/category/child-category/的页面时,WordPress会尝试加载带有slug“child-category”的帖子,而不是带有slug“child-category”的子类别。

// A hacky way of adding support for flexible custom permalinks
// There is one case in which the rewrite rules from register_kb_rewrite_rules() fail:
// When you visit the archive page for a child section(for example: http://example.com/faq/category/child-category)
// The deal is that in this situation, the URL is parsed as a Knowledgebase post with slug "child-category" from the "category" section
function fix_product_subcategory_query($query) {
    if ( isset( $query[\'post_type\'] ) && \'sps-product\' == $query[\'post_type\'] ) {
        if ( isset( $query[\'sps-product\'] ) && $query[\'sps-product\'] && isset( $query[\'product-category\'] ) && $query[\'product-category\'] ) {
            $query_old = $query;
            // Check if this is a paginated result(like search results)
            if ( \'page\' == $query[\'product-category\'] ) {
                $query[\'paged\'] = $query[\'name\'];
                unset( $query[\'product-category\'], $query[\'name\'], $query[\'sps-product\'] );
            }
            // Make it easier on the DB
            $query[\'fields\'] = \'ids\';
            $query[\'posts_per_page\'] = 1;
            // See if we have results or not
            $_query = new WP_Query( $query );
            if ( ! $_query->posts ) {
                $query = array( \'product-category\' => $query[\'sps-product\'] );
                if ( isset( $query_old[\'product-category\'] ) && \'page\' == $query_old[\'product-category\'] ) {
                    $query[\'paged\'] = $query_old[\'name\'];
                }
            }
        }
    }
    return $query;
}
add_filter( \'request\', \'fix_product_subcategory_query\', 10 );
此函数让WordPress知道如何在自定义帖子类型重写段塞结构中处理%product\\u category%:

function filter_post_type_link($link, $post)
{
    if ($post->post_type != \'sps-product\')
        return $link;

    if ($cats = get_the_terms($post->ID, \'product-category\'))
    {
        $link = str_replace(\'%product_category%\', get_taxonomy_parents(array_pop($cats)->term_id, \'product-category\', false, \'/\', true), $link); // see custom function defined below\\
        $link = str_replace(\'//\', \'/\', $link);
        $link = str_replace(\'http:/\', \'http://\', $link);
    }
    return $link;
}
add_filter(\'post_type_link\', \'filter_post_type_link\', 10, 2);
基于的自定义函数get_category_parents. 它获取分类法的父项:

// my own function to do what get_category_parents does for other taxonomies
function get_taxonomy_parents($id, $taxonomy, $link = false, $separator = \'/\', $nicename = false, $visited = array()) {    
    $chain = \'\';   
    $parent = &get_term($id, $taxonomy);

    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 .= get_taxonomy_parents($parent -> parent, $taxonomy, $link, $separator, $nicename, $visited);

    }

    if ($link) {
        // nothing, can\'t get this working :(
    } else    
        $chain .= $name . $separator;    
    return $chain;    
}
来源:

SO网友:user1676224

实际上,这是一种可怕的做法。

如果在自定义帖子类型之前/之上注册分类法,则可以使用自定义帖子类型重写规则为分类法添加前缀。

例如:。

if ( ! function_exists( \'type_taxonomy\' ) ) {

// Register Custom Taxonomy
function type_taxonomy() {

    $labels = array(
        \'name\'                       => _x( \'Types\', \'Taxonomy General Name\', \'asw\' ),
        \'singular_name\'              => _x( \'Type\', \'Taxonomy Singular Name\', \'asw\' ),
    );
    $rewrite = array(
        \'slug\'                       => \'update/type\',
        \'with_front\'                 => false,
        \'hierarchical\'               => false,
    );
    $args = array(
        \'labels\'                     => $labels,
        \'hierarchical\'               => true,
        \'public\'                     => true,
        \'show_ui\'                    => true,
        \'show_admin_column\'          => true,
        \'show_in_nav_menus\'          => true,
        \'show_tagcloud\'              => true,
        \'rewrite\'                    => $rewrite,
        \'show_in_rest\'               => true,
    );
    register_taxonomy( \'type\', array( \'updates\' ), $args );

}
add_action( \'init\', \'type_taxonomy\', 0 );

}

if ( ! function_exists(\'updates_post_type\') ) {

// Register Custom Post Type
function updates_post_type() {

    $labels = array(
        \'name\'                  => _x( \'Updates\', \'Post Type General Name\', \'asw\' ),
        \'singular_name\'         => _x( \'Updates\', \'Post Type Singular Name\', \'asw\' ),
    );
    $rewrite = array(
        \'slug\'                  => \'update\',
        \'with_front\'            => true,
        \'pages\'                 => true,
        \'feeds\'                 => true,
    );
    $args = array(
        \'label\'                 => __( \'Updates\', \'asw\' ),
        \'description\'           => __( \'Posts should include important updates on health, well being and community\', \'asw\' ),
        \'labels\'                => $labels,
        \'supports\'              => array( \'title\', \'editor\', \'thumbnail\' ),
        \'taxonomies\'            => array( \'type\', \'category\', \'post_tag\', \'brands\', \'markets\' ),
        \'hierarchical\'          => false,
        \'public\'                => true,
        \'show_ui\'               => true,
        \'show_in_menu\'          => true,
        \'menu_position\'         => 5,
        \'menu_icon\'             => \'dashicons-heart\',
        \'show_in_admin_bar\'     => true,
        \'show_in_nav_menus\'     => true,
        \'can_export\'            => true,
        \'has_archive\'           => true,
        \'exclude_from_search\'   => false,
        \'publicly_queryable\'    => true,
        \'rewrite\'               => $rewrite,
        \'capability_type\'       => \'page\',
        \'show_in_rest\'          => true,
    );
    register_post_type( \'updates\', $args );

}
add_action( \'init\', \'updates_post_type\', 0 );

}

结束

相关推荐

批量追加URL(向slug添加单词)

有没有办法在每个URL的末尾为帖子批量添加一个单词?我有大约3500个帖子,添加到每个帖子上会很耗时。例如,URL是www.example.com/my-post/ www.examle.com/new-post/ 我想在URL的末尾添加一个单词www.example.com/my-post-word/ www.examle.com/new-post-word/ 有MySql脚本来做这样的事情吗?