web-dev-qa-db-ja.com

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

すべてのWebリソースはカスタム投稿タイプのスラッグを削除するというテーマに基づいているようです。

yourdomain.com/CPT-SLUG/post-name 

現在は非常に古くなったソリューションで、pre WP バージョン3.5のインストールをしばしば参照しています。一般的なものは以下のとおりです。

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

register_post_type関数内でこれはもはや機能せず、誤解を招くものです。だから私はワードプレス5の瀬戸際で2018年第3四半期にコミュニティに尋ねる...

書き換え引数内などからカスタム投稿タイプ投稿のURLから投稿タイプスラッグを削除するための最新かつ効率的な方法は何ですか?

更新:これを正規表現で動作させるにはいくつかの方法があるようです。特にJan Beckからの回答は、競合するページ/投稿名が作成されないように常にコンテンツの作成を監視することをお勧めします。ただし、これは WP coreの主な弱点であると確信しています。それは私たちのために扱われるべきです。 CPT作成時のオプション/フックとしても、パーマリンク用の高度なオプションセットとしても。トラックチケットをサポートしてください。

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

43
Ben Racicot

次のコードは動作しますが、カスタム投稿タイプのスラッグがページまたは投稿のスラッグと同じ場合、競合が簡単に発生する可能性があることに注意してください。

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

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

「イベント」をカスタムの投稿タイプに変更するだけで、問題ありません。パーマリンクを更新する必要があるかもしれません。

57
Nate Allen

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

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

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

カスタム投稿タイプ分類ドキュメントを変更した後、Settings> Permalinksandre-saveに移動してみてください設定、それ以外の場合は404ページが見つかりません。

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

19
Mayank Dudakiya

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

実際のregister_post_typeのコードを wp-includes/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;

あなたは、関数alwaysが、空ではないスラッグ値を期待し、そうでなければ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呼び出しにスラッグが含まれなくなったことがわかります。 2つのシナリオをテストしました。

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

enter image description here 

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

enter image description here 

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

ここで答えを見てみると、上記で学んだことを組み合わせて、自動検出と重複するポストスラグの防止を追加する、より良い解決策の余地があると思います。

注:以下の例では、自分のCPT名の 'custom_post_type'を必ず変更してください。出現回数は多く、 '検索/置換'はそれらすべてを簡単に捉える方法です。このコードはすべて自分のfunctions.phpまたはプラグインに入れることができます。

ステップ1: 投稿を登録するときに書き換えを 'false'に設定することでカスタム投稿タイプの書き換えを無効にします。

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

ステップ2: / WordPressのbottomにカスタムの書き換えを手動で追加して、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' );

注:ニーズに応じて、上記の書き換えを変更することをお勧めします(トラックバックを無効にする、フィードを無効にするなど)。これらは、ステップ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 );

注:ページが要求されたときにロードできるのは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'が追加されます。このコードは、このソリューションを実装する前に重複しているスラグが既に存在する場合、それらを防ぐことはできません。必ず最初に重複を確認してください。

私はこれが彼らにとってもうまくいっているかどうかを確かめるためにこれを与えてくれる他の誰かからも聞きたいです。

5
Matt Keys

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

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

1
T.Todua

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

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

たくさんの404で終わった

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

本当にありがとう。

1

私がやったように子供の投稿に問題があったこれを読んでいる人のために私は最善の方法はあなた自身の書き換え規則を追加することであることがわかった。

私が抱えていた主な問題は、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を使えません。

書き換え規則を見てみると、最初のレベルと2番目のレベルでpagename以外のものと一致しているように見え(2番目のレベルは添付ファイルと一致していると思います)、適切な投稿にリダイレクトします。 3段階の深さではうまくいきません。

あなたがしなければならない最初のことは、同様に子供から投稿タイプのリンクを削除することです。上記のNate Allenの答えを見れば、この論理はここで起こるはずです。

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

私自身、投稿に子供がいるかどうか、正しいパーマリンクにたどり着くために何がないかをチェックするために、さまざまな条件を組み合わせて使用​​しました。この部分はそれほど複雑ではないので、他の場所でそれを実行している人々の例を見つけることができます。

しかし次のステップは、物事が与えられた答えから変わるところです。メインのクエリに何かを追加する代わりに(これはカスタム投稿とその子には有効でしたが、それ以上の子には有効ではありませんでした)私はWordPressのルールの最後に書き直しました。 404を押すと、カスタム投稿タイプ内のページが同じ名前であるかどうかを確認するための最後のチェックが1回行われます。それ以外の場合は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);

これが他の誰かに役立つことを願っています、私は子供の投稿の子とそれらからナメクジを削除するためにしなければならなかった何かを見つけることができませんでした。

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