使用 add_permastruct 返回常规帖子错误/404 的多个自定义 post_type URL 的自定义永久链接结构

the*_*ing 5 php wordpress url-rewriting

在我的 WP v6.1 中,我有两种自定义端口类型:companyproduct自定义分类法country

所需的 URL 结构分别为%country%/%company_postname%%country%/%product_postname%下面是代码$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=");
}
Run Code Online (Sandbox Code Playgroud)

使用上面的代码和另一个post_type_link过滤器函数,我可以生成自定义 URL。但是这个问题是正常的post,并且page没有发现帖子返回error_404

常规帖子/页面标准 URL 结构:www.example.com/%postname%

试过add_permastruct过帖子和页面,但没有成功。在拥有自定义帖子的自定义 URL 的同时,如何显示页面和帖子。

更新1 自定义帖子和分类法是通过代码创建的。

company代码示例

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);
Run Code Online (Sandbox Code Playgroud)

更新2

我的post_type_link功能是:

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;
}
Run Code Online (Sandbox Code Playgroud)

更新3

当永久链接设置为普通时www.example.com/?p=123,所有帖子、页面和自定义帖子都可以正常加载。

更新4

我发现帖子和页面没有使用single.phppage.php模板。它正在使用index.php. 然而,我没有在这些页面或帖子中附加任何模板。

更新 5 - 已解决

这是由于'rewrite' => array('slug' => '/', 'with_front' => FALSE)country定义分类法。没有这个rewrite现在页面和帖子都很好。

Mar*_*ark 1

你可以使用post_type_link钩子。

通过自定义重写添加自定义帖子类型和分类:

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);
Run Code Online (Sandbox Code Playgroud)

然后我们通过钩子对永久链接运行替换:

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 );
Run Code Online (Sandbox Code Playgroud)

更新:

使用此语法进行重写时,wordpress 似乎有一个怪癖,因此您需要在该术语前面加上前面。

'rewrite' => array( 'slug' => 'country/%country%', 'with_front' => false )
Run Code Online (Sandbox Code Playgroud)

并在替换帖子链接中:

return str_replace( 'country/%country%', $terms[0]->slug , $post_link );
Run Code Online (Sandbox Code Playgroud)

那么你的网址将是:

country/%country%/%company_postname%
Run Code Online (Sandbox Code Playgroud)

完成后,请确保刷新重写规则,方法是:设置 > 永久链接并单击“保存更改”