it-swarm.cn

从自定义帖子类型的帖子URL中删除蛞蝓

似乎所有的网络资源都基于删除自定义帖子类型slug的主题

yourdomain.com/CPT-SLUG/post-name 

现在是非常过时的解决方案,经常引用pre WP版本3.5安装。一个常见的是:

'rewrite'   => array( 'slug' => false, 'with_front' => false ),  

在register_post_type函数中。这不再有效并且具有误导性。所以我要求2018年第三季度的社区处于WordPress 5的边缘......

从重写参数或其他任何地方删除自定义帖子类型帖子的URL中的Post Type Slug的现代有效方法是什么?

更新:似乎有几种方法可以强制它与正则表达式一起使用。具体来说,Jan Beck的答案应该是你一直愿意监控内容创建,以确保没有创建冲突的页面/帖子名称......但是我确信这是WP核心的一个主要弱点它应该为我们处理。两者都是创建CPT时的选项/挂钩或永久链接的高级选项集。请支持轨道票。

脚注:请通过观看/推广来支持此trac门票: https://core.trac.wordpress.org/ticket/34136#ticket

43
Ben Racicot

以下代码将起作用,但您必须记住,如果您的自定义帖子类型的slug与页面或帖子的slug相同,则冲突很容易发生...

首先,我们将从永久链接中删除slug:

function na_remove_slug( $post_link, $post, $leavename ) {

    if ( 'events' != $post->post_type || 'publish' != $post->post_status ) {
        return $post_link;
    }

    $post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link );

    return $post_link;
}
add_filter( 'post_type_link', 'na_remove_slug', 10, 3 );

仅仅移除slu is是不够的。现在,你将得到一个404页面,因为WordPress只希望帖子和页面以这种方式运行。您还需要添加以下内容:

function na_parse_request( $query ) {

    if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
        return;
    }

    if ( ! empty( $query->query['name'] ) ) {
        $query->set( 'post_type', array( 'post', 'events', 'page' ) );
    }
}
add_action( 'pre_get_posts', 'na_parse_request' );

只需将“事件”更改为您的自定义帖子类型,就可以了。您可能需要刷新永久链接。

57
Nate Allen

将以下代码写入分类法注册。

'rewrite' => [
  'slug' => '/',
  'with_front' => false
]

代码更改后你必须做的最重要的事情

在您更改自定义帖子类型分类文档后,尝试转到 设置>永久链接 重新保存您的设置 ,否则您将找不到404页面。

点击此处查看最佳解决方案: http://www.krazzycodes.com/how-to-remove-custom-post-type-taxonomy-base-from-url-in-wordpress/

19
Mayank Dudakiya

我不久前试图解决这个问题,我所知道的简短回答是no。至少不是在重写参数内。

如果你看一下 wp-includes/post.php第1454行中的register_post_type的实际代码,那么很长的解释就会变得明显

add_permastruct( $post_type, "{$args->rewrite['slug']}/%$post_type%", $permastruct_args );

您可以在$args->rewrite['slug']重写标记中看到前缀%$post_type%。人们可以想到“让我们把slug设置为null然后”直到你看起来几行:

if ( empty( $args->rewrite['slug'] ) )
    $args->rewrite['slug'] = $post_type;

您可以看到函数always期望一个非空的slug值,否则使用post类型。

12
Jan Beck

响应 我以前的回答 :你当然可以在注册一个新的帖子类型时将rewrite参数设置为false并自己处理重写规则

<?php
function wpsx203951_custom_init() {

    $post_type = 'event';
    $args = (object) array(
        'public'      => true,
        'label'       => 'Events',
        'rewrite'     => false, // always set this to false
        'has_archive' => true
    );
    register_post_type( $post_type, $args );

    // these are your actual rewrite arguments
    $args->rewrite = array(
        'slug' => 'calendar'
    );

    // everything what follows is from the register_post_type function
    if ( is_admin() || '' != get_option( 'permalink_structure' ) ) {

        if ( ! is_array( $args->rewrite ) )
            $args->rewrite = array();
        if ( empty( $args->rewrite['slug'] ) )
            $args->rewrite['slug'] = $post_type;
        if ( ! isset( $args->rewrite['with_front'] ) )
            $args->rewrite['with_front'] = true;
        if ( ! isset( $args->rewrite['pages'] ) )
            $args->rewrite['pages'] = true;
        if ( ! isset( $args->rewrite['feeds'] ) || ! $args->has_archive )
            $args->rewrite['feeds'] = (bool) $args->has_archive;
        if ( ! isset( $args->rewrite['ep_mask'] ) ) {
            if ( isset( $args->permalink_epmask ) )
                $args->rewrite['ep_mask'] = $args->permalink_epmask;
            else
                $args->rewrite['ep_mask'] = EP_PERMALINK;
        }

        if ( $args->hierarchical )
            add_rewrite_tag( "%$post_type%", '(.+?)', $args->query_var ? "{$args->query_var}=" : "post_type=$post_type&pagename=" );
        else
            add_rewrite_tag( "%$post_type%", '([^/]+)', $args->query_var ? "{$args->query_var}=" : "post_type=$post_type&name=" );

        if ( $args->has_archive ) {
            $archive_slug = $args->has_archive === true ? $args->rewrite['slug'] : $args->has_archive;
            if ( $args->rewrite['with_front'] )
                $archive_slug = substr( $wp_rewrite->front, 1 ) . $archive_slug;
            else
                $archive_slug = $wp_rewrite->root . $archive_slug;

            add_rewrite_rule( "{$archive_slug}/?$", "index.php?post_type=$post_type", 'top' );
            if ( $args->rewrite['feeds'] && $wp_rewrite->feeds ) {
                $feeds = '(' . trim( implode( '|', $wp_rewrite->feeds ) ) . ')';
                add_rewrite_rule( "{$archive_slug}/feed/$feeds/?$", "index.php?post_type=$post_type" . '&feed=$matches[1]', 'top' );
                add_rewrite_rule( "{$archive_slug}/$feeds/?$", "index.php?post_type=$post_type" . '&feed=$matches[1]', 'top' );
            }
            if ( $args->rewrite['pages'] )
                add_rewrite_rule( "{$archive_slug}/{$wp_rewrite->pagination_base}/([0-9]{1,})/?$", "index.php?post_type=$post_type" . '&paged=$matches[1]', 'top' );
        }

        $permastruct_args = $args->rewrite;
        $permastruct_args['feed'] = $permastruct_args['feeds'];
        add_permastruct( $post_type, "%$post_type%", $permastruct_args );
    }
}
add_action( 'init', 'wpsx203951_custom_init' );

您可以看到add_permastruct调用现在不再包含slug了。我测试了两种情况:

  1. 当我使用slug“calendar”创建一个页面时,该页面被post类型存档覆盖,后者也使用了“calendar”slug。

enter image description here 

  1. 当我使用slug“my-event”创建一个页面并使用slug“my-event”创建一个事件(CPT)时,会显示自定义帖子类型。

enter image description here 

  1. 任何其他页面也不起作用。如果你看一下上面的图片,就会明白为什么:自定义帖子类型规则总是匹配页面slug。因为WordPress无法识别它是不存在的页面还是自定义帖子类型,所以它将返回404.这就是为什么你需要一个slug来识别页面或CPT。一个可能的解决方案是拦截错误并寻找可能存在的页面 类似于这个答案
7
Jan Beck

通过这里的答案,我认为有一个更好的解决方案的空间,结合我上面学到的一些东西,并添加自动检测和防止重复的后期slu ..

注意:请确保在下面的示例中为您自己的CPT名称更改“custom_post_type”。有很多事情,“查找/替换”是一种简单的方法来捕捉它们。所有这些代码都可以放在你的functions.php或插件中。

步骤1: 通过在注册帖子时将重写设置为“false”,禁用重写自定义帖子类型:

register_post_type( 'custom_post_type',
    array(
        'rewrite' => false
    )
);

第2步: 手动将我们的自定义重写添加到 bottom WordPress重写我们的custom_post_type

function custom_post_type_rewrites() {
    add_rewrite_rule( '[^/]+/attachment/([^/]+)/?$', 'index.php?attachment=$matches[1]', 'bottom');
    add_rewrite_rule( '[^/]+/attachment/([^/]+)/trackback/?$', 'index.php?attachment=$matches[1]&tb=1', 'bottom');
    add_rewrite_rule( '[^/]+/attachment/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$', 'index.php?attachment=$matches[1]&feed=$matches[2]', 'bottom');
    add_rewrite_rule( '[^/]+/attachment/([^/]+)/(feed|rdf|rss|rss2|atom)/?$', 'index.php?attachment=$matches[1]&feed=$matches[2]', 'bottom');
    add_rewrite_rule( '[^/]+/attachment/([^/]+)/comment-page-([0-9]{1,})/?$', 'index.php?attachment=$matches[1]&cpage=$matches[2]', 'bottom');
    add_rewrite_rule( '[^/]+/attachment/([^/]+)/embed/?$', 'index.php?attachment=$matches[1]&embed=true', 'bottom');
    add_rewrite_rule( '([^/]+)/embed/?$', 'index.php?custom_post_type=$matches[1]&embed=true', 'bottom');
    add_rewrite_rule( '([^/]+)/trackback/?$', 'index.php?custom_post_type=$matches[1]&tb=1', 'bottom');
    add_rewrite_rule( '([^/]+)/page/?([0-9]{1,})/?$', 'index.php?custom_post_type=$matches[1]&paged=$matches[2]', 'bottom');
    add_rewrite_rule( '([^/]+)/comment-page-([0-9]{1,})/?$', 'index.php?custom_post_type=$matches[1]&cpage=$matches[2]', 'bottom');
    add_rewrite_rule( '([^/]+)(?:/([0-9]+))?/?$', 'index.php?custom_post_type=$matches[1]', 'bottom');
    add_rewrite_rule( '[^/]+/([^/]+)/?$', 'index.php?attachment=$matches[1]', 'bottom');
    add_rewrite_rule( '[^/]+/([^/]+)/trackback/?$', 'index.php?attachment=$matches[1]&tb=1', 'bottom');
    add_rewrite_rule( '[^/]+/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$', 'index.php?attachment=$matches[1]&feed=$matches[2]', 'bottom');
    add_rewrite_rule( '[^/]+/([^/]+)/(feed|rdf|rss|rss2|atom)/?$', 'index.php?attachment=$matches[1]&feed=$matches[2]', 'bottom');
    add_rewrite_rule( '[^/]+/([^/]+)/comment-page-([0-9]{1,})/?$', 'index.php?attachment=$matches[1]&cpage=$matches[2]', 'bottom');
    add_rewrite_rule( '[^/]+/([^/]+)/embed/?$', 'index.php?attachment=$matches[1]&embed=true', 'bottom');
}
add_action( 'init', 'custom_post_type_rewrites' );

注意:根据您的需要,您可能需要修改上述重写(禁用引用?Feed?等)。这些代表了在步骤1中未禁用重写时生成的“默认”重写类型

第3步: 永久链接到您的自定义帖子类型'漂亮'再次

function custom_post_type_permalinks( $post_link, $post, $leavename ) {
    if ( isset( $post->post_type ) && 'custom_post_type' == $post->post_type ) {
        $post_link = home_url( $post->post_name );
    }

    return $post_link;
}
add_filter( 'post_type_link', 'custom_post_type_permalinks', 10, 3 );

注意:如果您不担心您的用户在另一种帖子类型中创建一个冲突(重复)帖子而不会担心这会导致在请求页面时只能加载其中一个帖子,则可以在此处停止。

步骤4: 防止重复的后塞

function prevent_slug_duplicates( $slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug ) {
    $check_post_types = array(
        'post',
        'page',
        'custom_post_type'
    );

    if ( ! in_array( $post_type, $check_post_types ) ) {
        return $slug;
    }

    if ( 'custom_post_type' == $post_type ) {
        // Saving a custom_post_type post, check for duplicates in POST or PAGE post types
        $post_match = get_page_by_path( $slug, 'OBJECT', 'post' );
        $page_match = get_page_by_path( $slug, 'OBJECT', 'page' );

        if ( $post_match || $page_match ) {
            $slug .= '-duplicate';
        }
    } else {
        // Saving a POST or PAGE, check for duplicates in custom_post_type post type
        $custom_post_type_match = get_page_by_path( $slug, 'OBJECT', 'custom_post_type' );

        if ( $custom_post_type_match ) {
            $slug .= '-duplicate';
        }
    }

    return $slug;
}
add_filter( 'wp_unique_post_slug', 'prevent_slug_duplicates', 10, 6 );

注意:这会将字符串'-duplicate'附加到任何重复的slugs的末尾。如果在实现此解决方案之前已存在重复的slu,则此代码无法阻止重复的slu。务必先检查重复项。

我很乐意听到其他任何人的回复,看看它是否适合他们。

5
Matt Keys

你不需要那么多硬编码。只需使用轻量级插件:

它有可定制的选项。

1
T.Todua

对于读过这个像我这样的儿童帖子有问题的人,我发现最好的方法是添加自己的重写规则。

我遇到的主要问题是,WordPress处理来自2个级别(子帖子)的页面的重定向,与处理3个级别(子帖子项)相比有点不同。

这意味着当我有/ post-type/post-name/post-child /我可以使用/ post-name/post-child时它会将我重定向到前面带有post-type的那个但是如果我有post-type /后名/后子/后孙子,然后我不能使用后名/后子/后孙子。

看一看重写规则,看起来它匹配第一级和第二级的页面名以外的东西(我认为第二级匹配附件),然后在那里做一些事情,将你重定向到正确的帖子。在三个级别深度它不起作用。

您需要做的第一件事是从子项中删除帖子类型链接。如果你看看Nate Allen的答案,这个逻辑应该在这里发生:

$post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link );

我自己使用了不同条件的混合来检查帖子是否有孩子等等,以便找到合适的永久链接。这部分不是太棘手,你会发现人们在其他地方做这件事的例子。

然而,下一步是事情从给定的答案发生变化。我没有在主要查询中添加内容(适用于自定义帖子及其子项而不是其他子项),而是添加了一个写入WordPress规则底部的重写,以便如果pagename没有检出并且它即将发布点击404它会做最后一次检查,以查看自定义帖子类型中的页面是否具有相同的名称,否则它会丢弃404。

这是我使用的重写规则,假设'event'是您的CPT的名称

function rewrite_rules_for_removing_post_type_slug()
{
    add_rewrite_rule(
        '(.?.+?)?(:/([0-9]+))?/?$',
        'index.php?event=$matches[1]/$matches[2]&post_type=event',
        'bottom'
    );
}

add_action('init', 'rewrite_rules_for_removing_post_type_slug', 1, 1);

希望这有助于其他人,我找不到任何与儿童职位的孩子有关的事情,并从那些中删除了slu ..

0
Moe Loubani

我们可以对上述功能进行一些修改:

function na_parse_request( $query ) {

if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
    return;
}

if ( ! empty( $query->query['name'] ) ) {
    $query->set( 'post_type', array( 'post', 'events', 'page' ) );
}
}

至:

function na_parse_request( $query ) {

if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
    return;
}

if ( ! empty( $query->query['name'] ) ) {

    global $wpdb;
    $pt = $wpdb->get_var(
        "SELECT post_type FROM `{$wpdb->posts}` " .
        "WHERE post_name = '{$query->query['name']}'"
    );
    $query->set( 'post_type', $pt );
}
}

为了设置正确的post_type值。

0
Max Kondrachuk

这对我有用:'rewrite' => array('slug' => '/')

0
Malki Mohamed