I have successfully created a custom post type with a URL rewrite that changes URLs from:
domain/post-type/slug
To:
domain/some-string/custom-field-value-1/custom-field-value-2/slug
This is working, but there have been some changes to my project that require me to do this instead:
domain/some-string/custom-field-value-1/custom-field-value-2/slug
domain/some-other-string/custom-field-value-1/custom-field-value-2/slug
Essentially, the first part of the path needs to be dynamic so that both "some-string" and "some-other-string" are valid.
I've updated the rewrite rules to accommodate this change, and those pages do work correctly, but none of the other pages on the site (except the front page) work at all. I'm seeing the header and footer, but no content.
Here's the relevant section of my custom post type registration:
'rewrite' => array(
'slug' => '%keyterms%/%community%/%address%',
'with_front' => false,
)
And here's my code:
function inventory_rewrite_tags() {
add_rewrite_tag('%keyterms%', '(.*)');
add_rewrite_tag('%community%', '(.*)');
add_rewrite_tag('%address%', '(.*)');
}
add_action('init', 'inventory_rewrite_tags');
function inventory_link_rewrite($link, $post) {
if($post->post_type === 'inventory') {
$community = get_field('community', $post->ID);
$address = get_field('address', $post->ID);
$possession_terms = wp_get_post_terms($post->ID, 'possession');
$build_type_terms = wp_get_post_terms($post->ID, 'build_type');
$ownership_terms = wp_get_post_terms($post->ID, 'ownership');
// Add keyterm
if($ownership_terms[0]->slug == 'rental') {
$link = str_replace('%keyterms%/', 'apartments-for-rent/', $link);
} else {
$link = str_replace('%keyterms%/', 'homes-for-sale/', $link);
}
// Add community
if($community) {
$link = str_replace('%community%/', $community[0]->post_name . '/', $link);
} else {
$link = $possession_terms ? str_replace('%community%/', $possession_terms[0]->slug . '/', $link) : $link;
}
// Add address
if($address) {
$link = str_replace('%address%/', sanitize_title($address) . '/', $link);
} else {
$link = $build_type_terms ? str_replace('%address%/', $build_type_terms[0]->slug . '/', $link) : $link;
}
}
return $link;
}
add_filter('post_link', 'inventory_link_rewrite', 10, 2);
Unfortunately creating a second post type is not an option.
I have successfully created a custom post type with a URL rewrite that changes URLs from:
domain/post-type/slug
To:
domain/some-string/custom-field-value-1/custom-field-value-2/slug
This is working, but there have been some changes to my project that require me to do this instead:
domain/some-string/custom-field-value-1/custom-field-value-2/slug
domain/some-other-string/custom-field-value-1/custom-field-value-2/slug
Essentially, the first part of the path needs to be dynamic so that both "some-string" and "some-other-string" are valid.
I've updated the rewrite rules to accommodate this change, and those pages do work correctly, but none of the other pages on the site (except the front page) work at all. I'm seeing the header and footer, but no content.
Here's the relevant section of my custom post type registration:
'rewrite' => array(
'slug' => '%keyterms%/%community%/%address%',
'with_front' => false,
)
And here's my code:
function inventory_rewrite_tags() {
add_rewrite_tag('%keyterms%', '(.*)');
add_rewrite_tag('%community%', '(.*)');
add_rewrite_tag('%address%', '(.*)');
}
add_action('init', 'inventory_rewrite_tags');
function inventory_link_rewrite($link, $post) {
if($post->post_type === 'inventory') {
$community = get_field('community', $post->ID);
$address = get_field('address', $post->ID);
$possession_terms = wp_get_post_terms($post->ID, 'possession');
$build_type_terms = wp_get_post_terms($post->ID, 'build_type');
$ownership_terms = wp_get_post_terms($post->ID, 'ownership');
// Add keyterm
if($ownership_terms[0]->slug == 'rental') {
$link = str_replace('%keyterms%/', 'apartments-for-rent/', $link);
} else {
$link = str_replace('%keyterms%/', 'homes-for-sale/', $link);
}
// Add community
if($community) {
$link = str_replace('%community%/', $community[0]->post_name . '/', $link);
} else {
$link = $possession_terms ? str_replace('%community%/', $possession_terms[0]->slug . '/', $link) : $link;
}
// Add address
if($address) {
$link = str_replace('%address%/', sanitize_title($address) . '/', $link);
} else {
$link = $build_type_terms ? str_replace('%address%/', $build_type_terms[0]->slug . '/', $link) : $link;
}
}
return $link;
}
add_filter('post_link', 'inventory_link_rewrite', 10, 2);
Unfortunately creating a second post type is not an option.
Share Improve this question asked Nov 19, 2019 at 23:00 hmakeinhmakein 686 bronze badges 3 |1 Answer
Reset to default 1The problem is with that add_rewrite_tag('%keyterms%', '(.*)')
, which results in rewrite conflicts because the generated rewrite rules would match http://example/(anything-here)
and that (anything-here)
can be a Page (post type page
) slug, hence http://example/page-slug
would not work — you wouldn't get a 404
error page, but the proper Page wouldn't be displayed, either.
So looking at your code, instead of using that (.*)
(which matches anything), you should instead specify the exact value, which in your case is either apartments-for-rent
or homes-for-sale
:
add_rewrite_tag('%keyterms%', '(apartments-for-rent|homes-for-sale)');
That should work, but be sure to flush the rewrite rules — just visit the permalink settings page.
UPDATE
Sorry, I wasn't aware WordPress isn't retaining the RegEx for all rewrite rules, specifically for attachments where WordPress removes the brackets ((
and )
):
// Relevant code in WP_Rewrite::generate_rewrite_rules().
$submatchbase = str_replace( array( '(', ')' ), '', $match );
And I know you changed the RegEx to ([aehomnprt]+s-for-[aelnrst]+)
which does work, although not as precise as the (apartments-for-rent|homes-for-sale)
.
So apart from the alternate RegEx, you can make (apartments-for-rent|homes-for-sale)
works like so (this code would go in the theme functions file):
add_filter( 'rewrite_rules_array', 'fix_inventory_rewrite_rules' );
function fix_inventory_rewrite_rules( $rules ) {
$rules2 = [];
$values = 'apartments-for-rent|homes-for-sale';
$_re = $values . '/';
$my_re = preg_quote( $_re, '/' );
foreach ( $rules as $regex => $query ) {
if ( preg_match( '/^' . $my_re . '/', $regex ) ) {
$regex = str_replace( $_re, '(' . $values . ')/', $regex );
}
$rules2[ $regex ] = $query;
}
return $rules2;
}
something-static/%keyterms%/
and not just%keyterms%/
. Otherwise, you'd run into404
errors because of rewrite conflicts. – Sally CJ Commented Nov 20, 2019 at 0:50