カスタム投稿タイプの投稿URLからスラッグを削除する


48

カスタム投稿タイプのスラッグを削除するというテーマに基づくすべてのウェブリソースは、つまり

yourdomain.com/CPT-SLUG/post-name 

WPバージョン3.5以前のインストールを参照することの多い非常に古いソリューションになりました。一般的な方法は次のとおりです。

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

register_post_type関数内。これはもはや機能せず、誤解を招きます。そこで、2018年第3四半期にWordPress 5の瀬戸際でコミュニティに質問します...

書き換え引数内またはその他の場所からカスタム投稿タイプの投稿のURLから投稿タイプのスラッグを削除する現代的で効率的な方法は何ですか?

更新:これを正規表現で動作させるにはいくつかの方法があるようです。特に、競合するページ/投稿名が作成されないようにコンテンツ作成を常に監視する場合、Jan Beckからの回答が必要になります。 。CPT作成時のオプション/フックとして、またはパーマリンクの高度なオプションセットとして。トラックチケットをサポートしてください。

脚注:https : //core.trac.wordpress.org/ticket/34136#ticketを見て/宣伝することで、このtracチケットをサポートしてください。


どうしてそんなことをしたいのか、頭を悩ませていると思いますか?混乱した。
マイケルエクルンド

3
@MichaelEcklund。公開されているWebページの作成に使用されるCPTには、URLに強制スラッグ名が含まれているためです。実際には、スラッグを安全に削除しようとしている多くのwp開発者がいます。
ベンラシコット

回答:


60

次のコードは機能しますが、カスタム投稿タイプのスラッグがページまたは投稿のスラッグと同じである場合、競合が簡単に発生する可能性があることに留意する必要があります...

まず、パーマリンクからスラッグを削除します。

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

ナメクジを取り除くだけでは十分ではありません。WordPressは、このように動作するのは投稿とページのみであるため、404ページが表示されます。また、次を追加する必要があります。

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

「イベント」をカスタム投稿タイプに変更するだけで準備完了です。パーマリンクを更新する必要がある場合があります。


ありがとう。これは、手動で書き換えを作成するよりも優れていると思いますか?私はその解決策を見てきましたが、それはあなたが言及した競合を寄せ付けないかもしれませんか?
ベンラシコット

1
条件のため、nginxで失敗します2 != count( $query->query )。nginxを使用すると、$ query-> query asを使用できますarray('page' => '', 'name' => '...', 'q' => '...')。@NateAllen、その状態の意味は何ですか?
ファビオモンテフスコロ

3
これよりも良いものが必要です。後で競合するURLを作成できないように、組み込みのスラッグを削除するサポート。通常の投稿とページがURLを作成する方法。
ベンラシコット

3
それは私だけですか、これはis_single()やis_singular()のようなワードプレスの条件タグを壊しますか?
ロブゴードン

1
残念なことに、この解決策によってリンクが破損し、ブログが投稿を表示しなくなり、通常のページになりました。以下のマットキーズの優れたソリューションをご覧ください。
ラドリーサステア

20

分類登録に次のコードを記述します。

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

コード変更後にしなければならない最も重要なこと

カスタム投稿タイプ分類ドキュメントを変更したら、[設定]> [パーマリンク]に移動して設定を保存直してください。そうしないと、404ページが見つかりません。

最適なソリューションについては、こちらをご覧くださいhttp : //www.krazzycodes.com/how-to-remove-custom-post-type-taxonomy-base-from-url-in-wordpress/


これは実際に機能しますが、これまで誰も気付いていなかったのです。もちろん、これが同じパーマリンクを持っている場合、他のページに干渉する可能性がありますが、そうでない場合、これは素晴らしい解決策です。
アレクサンダーĐorđević17年

4
これを試してみました。カスタム投稿タイプのリンクに望ましい結果が得られます。しかし、すべてのPOSTまたはPAGE投稿タイプのスラッグを「キャッチ」し、それらをカスタム投稿タイプのURL、次に404として解決しようとします。(はい、パーマリンクを保存しました)。
マットキー

4
これは機能しません。パーマリンクを更新した場合でも404を提供します。
クリスティーンクーパー

3
繰り返しますが、パーマリンク設定を再保存した後でも、投稿とページは機能しなくなりました(404)
amklose

1
このソリューションは、URLからスラッグを削除するために機能します。しかし、アーカイブページはもう機能しません。
アンナプルナ

13

私は少し前にこれを理解しようとしましたが私が知っていることからの短い答えはいいえです。少なくとも書き換え引数内からではありません。

あなたは、実際のコードを見れば、長い説明が明らかになりregister_post_typeのwp-含ま/ post.phpライン1454

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

書き換えタグのプレフィックス$args->rewrite['slug']を見ることができます%$post_type%nullいくつかの行を見るまで、「スラグを設定してみましょう」と考えることができます。

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

関数は常に空ではないスラッグ値を期待し、それ以外の場合は投稿タイプを使用することがわかります。


@JanBeckに感謝します。これが存在する主な理由はありますか?このコアファイルを条件付きでハックして、このルールから特定の投稿タイプを除外してみませんか?
ベンラシコット

9
Jan Beckへの答えを与える必要があります。WordPressには、リクエストを適切にルーティングするためにpost_typeスラグが必要です。このルールは、ネイティブのWPページ(スラッグなしでレンダリング)とカスタム定義の投稿タイプとの名前の競合を防ぎます。スラッグをハックすると、WordPressは「picnic」という名前のページと「picnic」という名前のイベント(カスタム投稿タイプ)の違いを知りません。
dswebsme

3
@dswebsme同意しましたが、URLを絶対に変更する必要がある状況があります。ネイティブにできない理由とそうでない理由以外に、どのように効率的に行うのですか?
ベンラシコット

7

応じて、私の前の回答:あなたはもちろん、設定することができます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呼び出しにスラグが含まれなくなったことがわかります。2つのシナリオをテストしました。

  1. スラッグ「カレンダー」でページを作成すると、そのページは「カレンダー」スラッグを使用する投稿タイプのアーカイブで上書きされます。

ここに画像の説明を入力してください

  1. スラッグ「my-event」とスラッグ「my-event」のイベント(CPT)を含むページを作成すると、カスタム投稿タイプが表示されます。

ここに画像の説明を入力してください

  1. 他のページも機能しません。上の図を見ると、理由が明らかになります。カスタム投稿タイプルールは常にページナメクジと一致します。WordPressには、ページまたは存在しないカスタム投稿タイプを識別する方法がないため、404を返します。そのため、ページまたはCPTを識別するためにスラッグが必要です。考えられる解決策は、エラーをインターセプトし、この回答と同様に存在する可能性のあるページを探すことです。

CPTのスラッグを削除することが目標である場合、CPTをURLに表示されないため、衝突しない一意の名前を付けることはできませんか?または、ページと同じ名前を付けた場合、ポストネームは競合する可能性がありますか?
ベンラシコット

私はこれが実際にすべてのページを壊すことを示すために私の答えを更新しました。スラッグがない場合、WPはページではなくCPTを探し、見つからない場合はエラーを返します。したがって、実際にはポストネームとは関係ありません。
ヤン・ベック

1
そうですか。ネイティブWPの投稿とページのような将来の競合するURLに「-1」を追加する書き換えルールが必要です。tracチケットを作成しましたcore.trac.wordpress.org/ticket/34136#ticketあなたの考えが大好きです。
ベンラシコット

7

ここで答えを見ると、上記で学んだことを組み合わせて、自動検出と重複したスラッグの防止を追加するより良いソリューションの余地があると思います。

注:以下の例では、独自のCPT名の「custom_post_type」を必ず変更してください。多くのオカレンスがあり、「検索/置換」はそれらすべてを簡単にキャッチする方法です。このコードはすべて、functions.phpまたはプラグインに入れることができます。

ステップ1:投稿の登録時に書き換えを「false」に設定して、カスタム投稿タイプの書き換えを無効にします。

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

ステップ2:カスタム書き換えをcustom_post_typeのWordPress書き換えの下部に手動で追加します

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

注:ニーズに応じて、上記の書き換えを変更することもできます(トラックバックを無効にしますか?フィード?など)。これらは、ステップ1で書き換えを無効にしなかった場合に生成される「デフォルト」の書き換えタイプを表します。

ステップ3:カスタム投稿タイプ「pretty」へのパーマリンクを再度作成する

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

注:ユーザーが別の投稿タイプで競合する(重複する)投稿を作成し、ページが要求されたときに1人のみがロードできる状況を作成することを心配しない場合は、ここで停止できます。

ステップ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」が追加されます。このコードは、このソリューションを実装する前に既に存在するスラッグの重複を防ぐことはできません。最初に重複を確認してください。

これを試してみて、それが彼らにとってもうまくいくかどうか確かめるために、他の誰かから返事を聞きたいです。


ただテストしてみたところ、今のところ機能しているようです。
クリスティーンクーパー

このアプローチには希望がありましたが、パーマリンクを再保存した後でも、CPTの投稿に404が表示されました。
ガルコニス

申し訳ありませんが、それはあなたのために動作しませんでした。私はしばらく前にこのことについて他の誰かと話していましたが、彼らは彼らのサイトでも問題を抱えていました。ブログの投稿のパーマリンクにプレフィックスが付いているかどうかが重要だったことを覚えているようです。私がブログ用に開発したサイトでは、パーマリンク構造を使用しています:/ blog /%postname%/。ブログの投稿に接頭辞がない場合は、それを受け入れることが許容されるので、試してみて、その方法を教えてください!
マットキーズ

2
これは私のために働いた。ページ上の他のソリューションとは異なり、通常のページやブログのレイアウトを壊すことはなく、無限のリダイレクトを引き起こすこともありませんでした。これらのcptページを編集するときに、「パーマリンク」領域に正しいURLを表示することもできます。ここでのかなり良い解決策は、唯一の注意点はアーカイブページが機能しないことです。ことを忘れないでください「custom_post_type」を入れ替える、その後、あなたのパーマリンクを更新
ラドリーサステア

@MattKeys、デフォルトのパーマリンク設定には、カスタム構造があり/%category%/%postname%/ます。コードを追加すると、CPTスラッグはOKに見えます(末尾のスラッシュはありませんが)...そして競合チェッカーも機能します。しかし404上の実際のポストの結果
Garconis

1

あなたはそんなにハードコードを必要としません。軽量プラグインを使用するだけです:

カスタマイズ可能なオプションがあります。


なぜあなたが投票されたのかがわかりました。通常のページリンクの解決を妨げます。更新にもかかわらず、既存のページのキャッシュコピーを取得していたため、表示されませんでした。
ウォルフ

@Walf問題について詳しく教えてください。
T.Todua

メインメニューから(カスタムの投稿タイプではない)ページへのリンクをたどると、ページが存在しないかのように404エラーが発生しました。それでおしまい。
ウォルフ

@Walf機会のURLの例を教えてください。おかげで(したい場合は、私はちょうど元の例を必要とし、ドメイン名をカバーすることができます)、私はそれを更新ウィル
T.Todua

1

ここでも同じ問題があり、ワードプレスのサイトには動きがないようです。単一のブログ投稿に構造/ blog /%postname%/が必要な私の特定の状況では、このソリューション

https://kellenmace.com/remove-custom-post-type-slug-from-permalinks/

たくさんの404で終わった

しかし、ブログポストにバックエンドのパーマリンク構造を使用していないこの素晴らしいアプローチと一緒に、最終的に魅力のように機能します。 https://www.bobz.co/add-blog-prefix-permalink-structure-blog-posts/

本当にありがとう。


0

上記の機能にいくつかの変更を加えることができます。

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

私がやったように子の投稿で問題を抱えているこれを読んでいる人にとって、私はあなた自身の書き換えルールを追加することが最善の方法だと思いました。

私が抱えていた主な問題は、WordPressが2レベル(子投稿)のページからのリダイレクトを、3レベル(子投稿の子)を扱うのとは少し異なることでした。

つまり、/ post-type / post-name / post-child /がある場合は、/ post-name / post-childを使用でき、post-typeが前にあるものにリダイレクトされますが、post-typeがある場合は/ post-name / post-child / post-grandchildその場合、post-name / post-child / post-grandchildは使用できません。

書き換えルールを見てみると、第1レベルと第2レベルでページ名以外のものに一致するように見え(第2レベルは添付ファイルに一致すると思います)、そこで適切な投稿にリダイレクトするために何かをします。3つのレベルの深さでは機能しません。

最初に行う必要があるのは、子からも投稿タイプのリンクを削除することです。上記のNate Allenの答えを見れば、このロジックはここで発生するはずです。

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

私は、さまざまな条件を組み合わせて使用​​して、適切なパーマリンクに到達するために、投稿に子とその他のものがあるかどうかを確認しました。この部分はそれほどトリッキーではなく、他の場所でそれをしている人々の例を見つけるでしょう。

ただし、次のステップは、与えられた答えから物事が変わるところです。メインクエリ(カスタムポストとその子に対しては機能するが、それ以上の子に対しては機能しない)に物事を追加する代わりに、ページ名がチェックアウトされず、 404を押すと、カスタム投稿タイプ内のページに同じ名前があるかどうかを確認する最後のチェックが行われます。そうでない場合は、404がスローされます。

「イベント」が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);

これが他の誰かを助けることを願っています、私は子の子の投稿に関係し、それらからナメクジを削除する必要がある他のものを見つけることができませんでした。


正規表現にタイプミスがあるようです。'(:'の間に、非キャプチャサブパターンとして使用するには '?'が必要です。このタイプミスがないと、式は組み込みの投稿タイプ「ページ」で見られるものと同じになります
jot
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.