問題描述

看起來所有的網頁資源都基於刪除自定義帖子類型 slug 的主題

yourdomain.com/CPT-SLUG/post-name

現在非常陳舊的解決方案通常引用了預裝 WP 3.5 安裝。一個常見的是:

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

在您的 register_post_type 功能。這不再奏效,誤導了。所以我要求社區在 2017 年第一季度在 WordPress 4.7.X 的邊…

從重寫參數或其他任何地方,從自定義帖子類型帖子的 URL 中刪除 Post Type Slug 的現代和高效方法是什麼?

腳註:請通過觀看/推廣來支持這張 trac 票:https://core.trac.wordpress.org/ticket/34136#ticket

最佳解決方案

以下代碼將會起作用,但您只需要牢記,如果您的自定義帖子類型的插件與頁面或帖子的插槽相同,則衝突可能會輕鬆發生

首先,我們將從永久鏈接中刪除 s::

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 );

只是去除 s 子是不夠的。現在,您將獲得一個 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' );

只需將”events” 更改為您的自定義帖子類型即可。您可能需要刷新您的固定鏈接。

次佳解決方案

不久之前,我試圖弄清楚這一點,而我所知道的簡短的答案是否定的。至少不能從重寫參數內。

如果您在 wp-includes/post.php line 1454 中查看 register_post_type 的實際代碼,那麼長的解釋變得很明顯:

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

您可以看到前綴 $ args-> 將 [‘slug’] 重寫為%$ post_type%重寫標記。人們可以認為 「讓我們把 s just to to then then then then」「」「」「」「」「」「」until until until until until until until:::::

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

您可以看到該函數總是期望一個不為空的段值,否則使用該 post 類型。

第三種解決方案

響應 my previous answer:您可以自定義 rewrite 參數到 false 註冊一個新的 post 類型,並自己處理這樣的重寫規則

<?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. 當我創建了一個頁面,其中的”calendar” 頁面被覆蓋的帖子類型存檔,也使用”calendar” slug 。

  1. 當我創建了一個帶有 s 子”my-event” 的頁面和一個事件 (CPT) 與 s lug “my-event”,顯示自定義的帖子類型。

  1. 任何其他頁面也不工作。如果你看看上面的圖片,那就很明白為什麼:自定義帖子類型規則總是與一個頁面插槽匹配。因為 WordPress 無法識別是否是一個頁面或不存在的自定義帖子類型,它將返回 404. 這就是為什麼您需要一個小塊來識別頁面或 CPT 。一個可能的解決方案是攔截錯誤並尋找可能存在 similar to this answer 的頁面。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。