Working on a client site I've encounter my worst enemy... WP URL rewrite :(. I actually can't figure it out and after many days trying and searching, I can't make it work.
What I'm trying to get is a permalink like this company.com/product/%product-name%/
regardless of the /parent/child/
nesting depth. I do need the functionalities of the hierarchical pages for other reasons, but it should not appear in the URL.
Here is my set up:
- Wordpress 4.4.1
Permalink settings set to
Post name
I created a hierarchical custom post type
product
with rewrite parameter to false.$args = array( 'label' => __( 'Product', 'domain' ), 'description' => __( 'Company products', 'domain' ), 'labels' => $labels, 'supports' => array( 'title', 'editor', 'excerpt', 'thumbnail', 'revisions', 'page-attributes' ), 'taxonomies' => array( 'category', 'post_tag' ), 'hierarchical' => true, 'public' => true, 'show_ui' => true, 'show_in_menu' => true, 'menu_position' => 5, 'show_in_admin_bar' => true, 'show_in_nav_menus' => false, 'can_export' => true, 'has_archive' => true, 'exclude_from_search' => false, 'publicly_queryable' => true, 'rewrite' => false, 'capability_type' => 'page', ); register_post_type( 'product', $args );
At this point the products don't have a pretty permalink, they look like this and they both work:
- First level:
company.com/?product=my-first-product
-> ok - Second level:
company.com/?product=my-first-product/child-product
-> ok
After that, I registered the rewrite rule and permastruct then flushed the rewrite rules by saving changes in the permalink settings page
function bvt_product_rewrite_rule() {
add_rewrite_rule(
'^product/([^/]+)/?$',
'index.php?post_type=product&pagename=$matches[1]',
'top'
);
add_permastruct( 'product', '/product/%product%/' );
}
add_action( 'init', 'bvt_product_rewrite_rule', 10 );
Now the permalinks where correctly displayed for first level page but not correct for child page. Also both levels gave me a 404 error.
- First Level:
company.com/product/my-first-product/
-> 404 - Second Level:
company.com/product/my-first-product/child-product/
-> 404
I also tried a solution given here https://wordpress.stackexchange.com/a/101077/86838 where it allowed to remove the parent slug from child permalink, but I was still unsuccessful
function bvt_product_flatten_hierarchies( $post_link, $post ) {
if ( 'product' != $post->post_type ) {
return $post_link;
}
$uri = '';
foreach ( $post->ancestors as $parent ) {
$uri = get_post( $parent )->post_name . "/" . $uri;
}
return str_replace( $uri, '', $post_link );
}
add_filter( 'post_type_link', 'bvt_product_flatten_hierarchies', 10, 2 );
I installed two plugins debug-bar and monkeyman-rewrite-analyzer to analyse the rewrite and query, but I keep can't make it work.
My last try was with wp-permastructure plugin with allow to set custom permalink to custom post type. Which enables the custom setting permastruct
in the rewrite
array option of the register_post_type
.
[...]
'publicly_queryable' => true,
'rewrite' => array(
'permastruct' => '/%postname%/',
),
'capability_type' => 'page',
[...]
With this setting and both previous custom rewrite/permatruct/flatten_hierarchies desabled, it worked as stated by the plugin description
- First Level:
company.com/my-first-product/
-> ok - Second Level:
company.com/child-product/
-> ok
But now the /product/
level is missing, and if I try to put it in the 'permastruct' => '/product/%postname%/'
config it brings me back to both a 404 error.
Which leads to my main question.
Is it possible to do what I need to or only as close as I could go with the latest plugin ?
Thanks already for anybody who will take the time to answer me, and maybe save me from my poor situation. Thanks
PS I can't insert more than two links in the body so here is the mentioned plugin links:
https://wordpress.org/plugins/debug-bar/
https://wordpress.org/plugins/monkeyman-rewrite-analyzer/
https://wordpress.org/plugins/wp-permastructure/
templates
. Make sure nothing is standing in your way there too. Personally I would stay away from plugins at first, and try to get your rewrite to work with the CPT argumentrewrite
.