不同的重写动态 slug 被视为重复

Posted

技术标签:

【中文标题】不同的重写动态 slug 被视为重复【英文标题】:Different rewritten dynamic slugs seen as duplicate 【发布时间】:2021-11-08 23:15:44 【问题描述】:

如果帖子标题不太容易理解,我很抱歉......

我有一个名为houses自定义帖子类型,我根据分类术语动态地重写 slug。分类法称为sizes术语bigsmall

当我创建 2 个具有 相同标题 的帖子时,即使重写功能使其成为不同的 slug,slug 的输出也是这样的:

房屋/大/红房子 houses/small/red-house-2

我什至尝试手动更改编辑选项上的 slug,但它不允许我,它仍然在 slug 的末尾留下-2。数据库也是如此,它重定向到第一个帖子......

我不明白为什么 wordpress 将它们视为相同的 slug... 没有识别重写?

这里是我如何创建自定义帖子类型

$labels = array(
        'name'              => 'Houses',
        'singular_name'     => 'House',
        'menu_name'         => 'Houses',
        'search_items'      => 'Houses'
    );
    $args = array(
        'labels'                => $labels,
        'public'                => true,        
        'hierarchical'          => false,
        'exclude_from_search'   => false,
        'publicly_queryable'    => true,
        'menu_icon'             => 'dashicons-admin-home',
        'supports'              => array('title', 'editor'),
        'taxonomies'            => array('sizes', 'post_tag'), // Term & Tag
        'has_archive'           => false,
        'rewrite'               => array( 'slug' => 'houses/%sizes%'),
        'query_var'             => true
    );
    register_post_type('houses', $args);

这是我的分类法代码:

$labels = array(
        'name'              => 'Sizes',
        'singular_name'     => 'Size',
        'menu_name'         => 'Sizes',
    );
    $args = array(
        'labels'            => $labels, // display name
        'hierarchical'      => true,
        'public'            => true,
        'show_ui'           => true,
        'show_in_rest'      => true,
        'show_admin_column' => true,
        'query_var'         => true,
        'with_front'        => true
    );
    register_taxonomy( 'sizes', 'houses', $args); // Slug, CPT, array

这是我用来动态更改 slugs 的代码:

function houses_link( $post_link, $id = 0 )

    $post = get_post($id);

    if ( is_object( $post ) )
    
        $terms = wp_get_object_terms( $post->ID, 'houses' );

        if( $terms )
        
            return str_replace( '%sizes%' , $terms[0]->slug , $post_link );
        
    
    return $post_link;  

add_filter( 'post_type_link', 'houses_link', 1, 3 );

希望我的解释清楚:') 感谢您的帮助!

【问题讨论】:

其实这是个好问题。 Wordpress 在houses 帖子类型下两次看到“红房子”,因此它不会接受具有相同标题和 slug 的两个帖子。当您尝试创建新帖子时,重写规则不会触发,因此,它在生成帖子 slug 的那一刻不起作用。但是,有一种方法可以随心所欲地操纵蛞蝓。例如,您可以在帖子标题的末尾添加一个分类学 slug 而不是递增的数字 @Ruvee 非常感谢您的帮助!是的,我想在 slug 之后删除 -2 或任何其他数字,遗憾的是,我无法在 slug 中添加更多内容......在这两种情况下它都必须以 red-house 结尾:(我不不知道 wordpress 是否有可能在创建帖子的同时重写 slug?或者更新或刷新永久链接的方法?我已经尝试过 Settings>Permalinks>Save 不能告诉你我的头顶。我会处理它,如果我能够让它工作,请告诉你。 @Ruvee 感谢您的帮助! :') 【参考方案1】:

首先我们需要解释一下 Wordpress 中的 rewrite_rules 和页面 url 生成是如何工作的

这里是最简单的网址

https://example.com/?p=1

当您访问它时,Wordpress 会搜索 ID = 1 的帖子并输出一个页面。如果没有找到,它会返回 404。

现在有点复杂的网址

https://example.com/?name=hello-world

我们在 url 中有一个 slug 而不是 ID,所以 Wordpress 与第一个一样工作,它在数据库中查找这个 slug 并为我们提供页面。

现在让我们看看启用永久链接的页面的 url

https://example.com/hello-world/

当 Wordpress 看到这样的 url 时会发生什么? 它会转到其 rewrite_rules 列表以查看该 url 是否存在正则表达式。

使用正则表达式,我们从 url 中提取关键数据并向标准 url 发送请求

https://example.com/?name=hello-world

现在让我们看看你的网址

https://example.com/houses/big/red-house

当 Wordpress 看到这个 url 时,它会在 rewrite_rules 列表中为它找到合适的正则表达式,提取 'red-house' slug,然后发送请求到

https://example.com/?houses=red-house

这就是为什么在 Wordpress 中创建帖子时会检查以确保 slug 对于 post_type 是唯一的 因为有了这些链接

https://example.com/houses/small/red-house

https://example.com/houses/medium/red-house

https://example.com/houses/giga/red-house

Wordpress 会做和第一个链接一样的事情,它将请求发送到

https://example.com/?houses=red-house.

Wordpress 对单页没有 slug+term 的请求,只有 slug。

我们应该怎么做才能解决这个问题?

它不一定是一个整体的 slug,我们可以从 url 的不同部分组装它

我们需要做什么:

    添加 custom_field 'house_base_slug',因为在 post_type_link 之后,slug 将不再可编辑。 创建一个函数,从我们的 custom_field 和 term slug 创建一个唯一的“TermSlug-and-house_base_slug”格式 slug
add_action( 'save_post_houses', 'house_save_new_slug' );
function house_save_new_slug($post_id) 
    
        //disable
        remove_action( 'save_post_houses', 'house_save_new_slug' );

        $house_base_slug = get_post_meta($post_id, "house_base_slug", true);
        if($house_base_slug =='') 
        $house_base_slug = $post_id;
        
        $terms = wp_get_object_terms( $post_id, 'sizes' );
        
        $term_slug = $terms[0]->slug;
        if($term_slug == "") 
        $term_slug = 'default';    
        
        $new_house_slug = $term_slug . '-and-' .  $house_base_slug;
        // update the post. At this time the save_post hook is triggered
        wp_update_post( array( 'ID' => $post_id, 'post_name' => $new_house_slug ) );
        clean_post_cache( $post_id );
        // Enable
        add_action( 'save_post_houses', 'house_save_new_slug' );

这里有一点很重要,我们更新 post_name(slug) 这会触发 save_post 钩子 为了避免循环,我们在更新之前禁用我们的功能

remove_action('save_post_houses', 'house_save_new_slug');

然后我们将其重新打开

add_action('save_post_houses', 'house_save_new_slug' );

现在,当您创建或更新房屋时,将自动创建这种格式为“TermSlug-and-house_base_slug”的 slug。 如果我们的 custom_field 'house_base_slug' 为空 - post_id 将被采用。 如果没有术语 - 将使用 slug 'default'

    好的,现在我们有了一个“小红屋”蛞蝓。 我们必须将它与我们的网址相关联
add_action( 'init', 'rewrite_rule_my_house' );
function rewrite_rule_my_house()
  add_rewrite_rule( '^houses/([^/]*)/([^/]*)/?', 'index.php?houses=$matches[1]-and-$matches[2]', 'top' );

在这一步之后别忘了禁用/启用永久链接,我们需要重置缓存。

    更新固定链接
function custom_post_permalink( $permalink, $post, $leavename, $sample ) 

    if ( $post->post_type == 'houses'  ) 

      $post_name = $post->post_name;
      $post_name_exploded = explode('-and-', $post_name);
      $current_slug_part1 = $post_name_exploded[0];
      $current_slug_part2= $post_name_exploded[1];
      $post_cur_id = $post->ID;
      

      
      $slug = '/houses/' . $current_slug_part1 .'/' . $current_slug_part2 . '/';

      
      $permalink = home_url($slug, 'https');
    
    return $permalink;  

add_filter( 'post_type_link', 'custom_post_permalink', 10, 4 );

【讨论】:

抱歉回复晚了,非常感谢您的帮助!我删除了 动态改变 slug 的部分 并添加了你的。想要创建一个新帖子时出现了一些关于未定义值的错误:(幸运的是,我仍然可以输入信息。创建帖子后,url不正确。它输出像这样houses/small/77(使用id)直到我点击更新按钮它输出了它应该如何houses/small/red-house。蛞蝓是我需要的,但现在当我点击链接时,它会将我带到一个404页面......我清理了永久链接但仍然没有出现:(一如既往地感谢! 你添加新的 add_rewrite_rule 到 functions.php ? 我又检查了一次,代码在我的演示 wordpress 上工作。如果仍然无法在您的 wp 上工作 - 从管理面板制作房屋页面和房屋列表的完整屏幕截图并在此处发布链接

以上是关于不同的重写动态 slug 被视为重复的主要内容,如果未能解决你的问题,请参考以下文章

壁纸应用程序是不是被视为重复内容?

使 post slug 独一无二

使用 Gatsby mdx.slug 的重复页面

Django:使用重复的 slug 管理诸如 id:slug 之类的 url

“蛞蝓”是啥意思[重复]

Codeigniter 博客应用程序:避免 slug 的重复输入错误