通过分类法定义自定义帖子类型的永久链接

时间:2012-11-25 18:15:13

标签: wordpress custom-post-type permalinks

我想为产品和产品类型创建规范的永久链接。我有自定义的帖子类型和自定义分类法,但我不知道是否可以用分类法定义永久链接。所以我的工作流程就是这样......

  1. 我创建了一个名为产品的自定义帖子类型。
  2. 然后,我为产品类型创建了自定义分类。
  3. 然后我添加一个名为'Chairs'的产品类型,并添加一个名为的产品 'Red Chair'到此类别。
  4. 创建此产品后,所需的永久链接结构即可查看此产品     格式如此 - >

    http://shop.com/products/chairs/red-chair
    

    这在wordpress 3.4中是否可行?我的自定义帖子类型中的元框允许选择为我的自定义分类法定义的产品类型,每个产品只会有一种类型。

    如果可能,我还希望尽可能包括所选产品类别的所有家长(例如,如果'主席'类别是'贵宾室'的孩子< / strong>类别,永久链接结构如下 - &gt;

    http://shop.com/products/lounge/chairs/red-chair
    

    以下是我创建自定义帖子类型和自定义分类的方法,我只需要帮助定义重写/ slug规则以在永久链接中包含产品类型。

    /* Custom Post Type - Products ------- */
    function products_init() {
        $args = array(
            'public' => true,
            'label' => 'Products'
        );
        register_post_type( 'products', $args );
    }
    add_action( 'init', 'products_init' );
    
    /* Custom Taxonomy - Product Type ------- */
    add_action( 'init', 'create_prodtype' );
    function create_prodtype() {
        $labels = array(
            'name' => _x( 'Product Type', 'products' ),
            'singular_name' => _x( 'Product Category', 'product' ),
            'search_items' =>  __( 'Search Product Types' ),
            'all_items' => __( 'All Product Types' ),
            'parent_item' => __( 'Products' ),
            'parent_item_colon' => __( 'Products:' ),
            'edit_item' => __( 'Edit Product Type' ),
            'update_item' => __( 'Update Product Type' ),
            'add_new_item' => __( 'Add New Product Type' ),
            'new_item_name' => __( 'New Product Type' ),
        );
        register_taxonomy(
            'products',
            array('products'),
            array(
                'rewrite' => array(
                    'slug' => 'products',
                    'hierarchical' => true
                ), 
                'with_front' => false,
                'labels' => $labels
        ));
    }
    

2 个答案:

答案 0 :(得分:14)

<强>解决方案

我在Jan Fabry的这些帖子的帮助下找到了它 - &gt;

  

https://wordpress.stackexchange.com/a/5478/10350   https://wordpress.stackexchange.com/a/22490/10350

我已设置自定义帖子类型,如下所示 - &gt;

  • 自定义帖子类型(register_post_type) - &gt;的 “产品”
  • 分类法(register_taxonomy) - &gt;的 “产品类型”

后端功能

我重写了保存在后端的固定链接结构,以便保存永久链接以包含自定义分类法类型 - “product-type”

add_filter('post_type_link', 'product_type_permalink', 10, 4);
function product_type_permalink($post_link, $post, $leavename, $sample) {
    //If is custom post type "product"
    if ($post->post_type == 'product') {
        // Get current post object
        global $post;
        // Get current value from custom taxonomy "product-type"
        $terms = get_the_terms($post->id, 'product-type');
        // Define category from "slug" of taxonomy object
        $term = $terms[0]->slug;
        // Re-structure permalink with string replace to include taxonomy value and post name
        $permalink = str_replace('product/', 'product/' . $term . '/', $post_link);
    }
    return $permalink;
}

永久链接设置设置为“帖子名称”并保存。如果将产品添加到类别并保存,则应重新编写永久链接以包括自定义分类法定义,在本例中为“product-type”。因此,如果您将“Red Chair”添加到“Chairs”类别,则网址格式如下 - &gt;

http://website.com/product/chairs/red-chair/

但如果您尝试转到此页面,则会收到404错误。这是因为wordpress还不知道如何使用此URL查询数据库,因此您必须编写它。

前端功能

我们需要添加重写规则,以便wordpress可以获取我们的URL并查询数据库。我们使用wordpress函数add_rewrite_rule将给定的永久链接转换为查询字符串。

add_rewrite_rule(
    // The regex to match the incoming URL
    'product/([^/]+)/([^/]+)/?',
    // The resulting internal URL: `index.php` because we still use WordPress
    // `pagename` because we use this WordPress page
    // `designer_slug` because we assign the first captured regex part to this variable
    'index.php?product-type=$matches[1]&product=$matches[2]',
    // This is a rather specific URL, so we add it to the top of the list
    // Otherwise, the "catch-all" rules at the bottom (for pages and attachments) will "win"
    'top'
);

在此函数中,matches阵列由Wordpress定义,在每个斜杠处展开给定的字符串。因此,在此示例中,正则表达式([^/]+)用于匹配每个斜杠之间的任何内容。在此示例中有2个级别,因此它匹配产品类型,然后是产品,并将它们添加到匹配数组,其中product-type = $匹配1,product = $匹配[2]。

此重写规则将此转换为&gt;

product/chairs/red-chair/

进入 - &gt;

index.php?product-type=chair&product=red-chair

我们的数据库可用于查询数据库并使用格式化的永久链接返回正确的产品页面。

这会抛弃产品类型的页面,因为url,product-type中只有一个级别。这意味着重写规则目前将始终尝试识别查询字符串中定义的产品名称。所以为此,我们还编写了一个单级重写规则:

add_rewrite_rule('^product/([^/]*)?$','index.php?product-type=$matches[1]','top');

现在这也将查询产品类型页面,因此如果我们想要显示各种产品类型,我们可以像往常一样循环分类,当我们尝试链接到它们时不会抛出404错误。

<强>下行

目前这只会采用单一级别的分类,因此自定义分类结构不能是分层的。如果指定多个分类,则将使用具有第一个ID的最多分类来定义永久链接。一个潜在的解决方法是隐藏自定义帖子类型的侧栏中显示的自定义分类菜单,并为分类法添加一个元框,其中只能使用选择框。我为此使用了Meta Box plugin。 (nb,这个插件没有任何管理菜单,它允许你只是通过创建数组在你的functions.php中为自定义帖子类型编写元框 - 强烈推荐!)

答案 1 :(得分:1)

@reekogi这适用于产品自定义帖子类型,但会中断所有其他帖子类型。

add_filter('post_type_link', 'product_type_permalink', 10, 4);
function product_type_permalink($post_link, $post, $leavename, $sample) {
    //If is custom post type "product"
    if ($post->post_type == 'product') {
        // Get current post object
        global $post;
        // Get current value from custom taxonomy "product-type"
        $terms = get_the_terms($post->id, 'product-type');
        // Define category from "slug" of taxonomy object
        $term = $terms[0]->slug;
        // Re-structure permalink with string replace to include taxonomy value and post name
        $permalink = str_replace('product/', 'product/' . $term . '/', $post_link);
    }
    return $permalink;
}

修复将更改vars $ post_link和$ permalink to $ url

function product_type_permalink($url, $post, $leavename, $sample) {
    //If is custom post type "product"
    if ($post->post_type == 'product') {
        // Get current post object
        global $post;
        // Get current value from custom taxonomy "product-type"
        $terms = get_the_terms($post->id, 'product-type');
        // Define category from "slug" of taxonomy object
        $term = $terms[0]->slug;
        // Re-structure permalink with string replace to include taxonomy value and post name
        $url = str_replace('product/', 'product/' . $term . '/', $url);
    }
    return $url;
}
add_filter('post_type_link', 'product_type_permalink', 10, 4);