Permalinks so that one custom post type appears to be a child of another, not working

Currently I have two post types, “products” and “products-data” they are separate post types; however, for all intents and purposes products-data is a child post of products. The relation is established via a meta element for products-data “parent” that will have a products post’s post ID.

The “products-data” posts are created only one way — a user clicks on a product in the products post type and enters data into a popup window. This uses wp_insert_post to create a products-data post and it adds a meta element “parent” with the value of the “products” post’s ID. This data is displayed via a modal window if a user clicks on the product type.

I am trying to have their permalinks as follows:

Permalink schema for a “products” post (for this example this post’s ID is 123):

http://example.com/products/new-product-1/

Permalink schema for a “products-data” post that has a meta key/value of parent=>123

http://example.com/products/new-product-1/information-product-data/

Here is the code I am using to register the post type and create rewrite rules; however, after adding this code and flushing my rewrite rules (settings>permalink) it works fine for a “products-data” post type BUT when I try to access a “products” post it displays the homepage for the WordPress site (N.B. this is not via redirect, the URL bar displays the “products” URL).

I am wondering if the issue is that the two permastructs appear that they can collide with each other, however there will never be an instance of this in practice due to the permastructs schema.

Any help would be greatly appreciated on how to resolve this.

Code:

add_action ( 'init', 'register_product_post_types' );
add_action ( 'init', 'products_add_rewrite_rules' );
add_filter ( 'post_type_link', 'products_permalinks', 10, 3 );

function register_product_post_types() {    
    register_post_type( 'products',
        array(
                'supports' => array( 'title', 'editor', 'author',"custom-fields", "thumbnail", "excerpt", 'comments' ),
                'labels' => array(
                'name' => __( 'Products' ),
                'singular_name' => __( 'Products' )
            ),
        'public' => true,
        'has_archive' => false,
        'rewrite' => FALSE,
        )
    );

    register_post_type( 'products-data',
        array(
                'supports' => array( 'title', 'editor', 'author',"custom-fields" ),
                'labels' => array(
                'name' => __( 'Products-Data' ),
                'singular_name' => __( 'Products-Data' )
            ),
        'show_in_menu' =>'edit.php?post_type=products',
        'public' => true,
        'has_archive' => false,
        'rewrite' => FALSE,
        )
    );
}


function products_add_rewrite_rules() {
    global $wp_rewrite;
    $wp_rewrite->add_rewrite_tag('%products%', '([^/]+)', 'products=");
    $wp_rewrite->add_rewrite_tag("%products-data%', '([^/]+)', 'products-data=");
    $wp_rewrite->add_rewrite_tag("%parent%', '([^/]+)', 'parent=");
    $wp_rewrite->add_permastruct("products-data', '/products/%parent%/%products-data%', false);

}

function products_permalinks($permalink, $post, $leavename) {
    $no_data="no-data";
    $post_id = $post->ID;
    if($post->post_type != 'products-data' || empty($permalink) || in_array($post->post_status, array('draft', 'pending', 'auto-draft')))
        return $permalink;
    $data = sanitize_title(get_the_title(get_post_meta($post_id, 'parent', true)));
    if(!$data) $data = $no_data;
    $permalink = str_replace('%parent%', $data, $permalink);
    return $permalink;
}

1 Answer
1

See my answer here: https://wordpress.stackexchange.com/a/100486/12324.

The issue you’re facing is that permastructs are adding multiple custom post types to the URL, which is confusing WordPress. You’ll need to add your rewrite rules using add_rewrite_rule().

Leave a Comment