Reputation: 844
In my WP v6.1, I have two custom port types: company
, product
and custom taxonomy country
.
Desired URL structure is %country%/%company_postname%
and %country%/%product_postname%
respectively and below is the code for $wp_rewrite
:
add_action('init', 'custom_init');
function custom_init() {
global $wp_rewrite;
$company_url = '/%country%/%company_postname%';
$product_url = '/%country%/%product_postname%';
$wp_rewrite->add_permastruct('company', $company_url, false);
$wp_rewrite->add_permastruct('product', $product_url, false);
$wp_rewrite->add_rewrite_tag("%company_postname%", '([^/]+)', "company=");
$wp_rewrite->add_rewrite_tag("%product_postname%", '([^/]+)', "product=");
}
With above code and another post_type_link
filter function, I am able to generate my custom URLs. However the issue is regular post
and page
posts are not found returning error_404
.
Regular post / page standard URL structure: www.example.com/%postname%
Have tried add_permastruct
for posts & pages, but that did not worked. How do I show pages and posts while having the custom URLs for my custom posts.
Update 1 Custom posts and taxonomies were created by code.
Example of company
code
function company_post_type() {
$labels = array(
'name' => _x('Company', 'Post Type General Name', 'text'),
);
$args = array(
'labels' => $labels,
'supports' => array('title', 'editor', 'custom-fields'),
'taxonomies' => array('country'),
'query_var' => true,
'rewrite' => false
);
register_post_type('company', $args);
}
add_action('init', 'company_post_type', 0);
Update 2
And my post_type_link
function is:
function post_type_link_function($url, $post) {
// only if post is published
if ('' != $url && !in_array($post->post_status, array('draft', 'pending', 'auto-draft'))) {
// get country terms
$terms = wp_get_object_terms($post->ID, 'country');
// country
if (strpos($url, '%country%') !== FALSE) {
if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) {
$country = urlencode($terms[0]->slug);
$url = str_replace('%country%', $country, $url);
}
}
// post names
$postnames = array('%company_postname%', '%product_postname%', '%postname%');
foreach ($postnames as $postname) {
$postname = $post->post_name;
$url = str_replace($postnames, $postname, $url);
}
return $url;
}
return $url;
}
Update 3
When permalinks set to Plain www.example.com/?p=123
, all posts, pages and custom posts are loading fine.
Update 4
I have observed that posts and pages are not using either single.php
or page.php
template. It is using index.php
.
Whereas, I have not attached any templates to these pages or posts.
Update 5 - resolved
It was due the 'rewrite' => array('slug' => '/', 'with_front' => FALSE)
in the country
custom taxonomy.
Without this rewrite
now the pages and posts are fine.
Upvotes: 6
Views: 798
Reputation: 3648
You can use the post_type_link
hook.
Add your custom post type and taxonomy with your custom rewrite:
function company_post_type() {
$labels = array(
'name' => _x('Company', 'Post Type General Name', 'text'),
);
$args = array(
'labels' => $labels,
'show_ui' => true,
'public' => true,
'publicly_queryable' => true,
'supports' => array('title', 'editor', 'custom-fields'),
'taxonomies' => array('country'),
'query_var' => true,
'rewrite' => array( 'slug' => '%country%', 'with_front' => false ),
);
register_post_type('company', $args);
$tax_args = array(
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'show_in_rest' => true,
);
register_taxonomy( 'country', 'company', $tax_args );
}
add_action('init', 'company_post_type', 0);
then we run a replace on the permalink via the hook:
function replace_post_link( $post_link, $id = 0 ){
$post = get_post($id);
$post_type = get_post_type( $id );
if ( is_object( $post ) && $post_type == 'company'){
$cat = 'country';
$terms = wp_get_object_terms( $post->ID, $cat );
if( $terms && !is_wp_error($terms) ){
return str_replace( '%country%' , $terms[0]->slug , $post_link );
}
}
return $post_link;
}
add_filter( 'post_type_link', 'replace_post_link', 1, 3 );
UPDATE:
There seems to be a quirk with wordpress when using this syntax for your rewrite so you will need to preface the term with a front.
'rewrite' => array( 'slug' => 'country/%country%', 'with_front' => false )
and in the replace post link:
return str_replace( 'country/%country%', $terms[0]->slug , $post_link );
Then your URL will be:
country/%country%/%company_postname%
make sure to flush your rewrite rules when you are done by going to: Settings > Permalinks and clicking 'save changes'
Upvotes: 1