web-dev-qa-db-ja.com

CPTのためのパーマリンクはページへのパーマリンクを壊す

私は「ルート」パーマリンクを持ちたいCPTを持っています。

そのため、「Foo Bar」というページの場合は、次のURLにします。

https://example.org/foo-bar

register_post_type( 'my_CPT', $args );argsに次の行を追加してCPTを登録することでこれを達成できることがわかりました。

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

しかし、それを追加すると、私のページへのパーマリンクは機能しません。私は理想的にそれらにこれらのパーマリンクを与えるだろう:

https://example.org/page/some-page

それ、どうやったら出来るの?

2
Zeth

ページは、どのURLに対してもデフォルトの解析可能性があるようにハードコードされています(または他に何も一致しない場合、wordpressはページを見つけようとします)。

そのため、 "接頭辞"を付けずにパーマリンク構造を置くのは賢明ではありませんが、本当にそのようにしたい場合は、 "ページ"スラッグを持つページを追加し、他のすべてのページを息子にするだけです。あなたが多くのページを持っていなくて、あなたが心配するためにパースとパーマリンク生成をハックするゼロコードを持っているなら、これはとてもうまくいくでしょう;)

2
Mark Kaplun

WordPressは書き換え規則を使ってリクエストを解析します。つまり、リクエストがいずれかのルールに一致すると、そのルールを使用して解析されます。

ページのルールは、以前のどのルールとも一致しなかったリクエストの大部分をキャッチするために行われた最後のルールの1つです。スラグなしでCPTを追加した場合、ページルールは無効になりません...

これを修正する1つの方法は、CPTをスラッグに登録してから、リンクとWPの動作を変更することです。これがコードです:

function register_mycpt() {
    $arguments = array(
        'label' => 'MyCPT',
        'public' => true,
        'hierarchical' => false,
        ...
        'has_archive' => false,
        'rewrite' => true
    );
    register_post_type('mycpt', $arguments);
}
add_action( 'init', 'register_mycpt' );

これでこれらの投稿のURLは次のようになります。

http://example.com/mycpt/{post_name}/

しかし、post_type_linkフィルタを使用してこれを簡単に変更できます。

function change_mycpt_post_type_link( $url, $post, $leavename ) {
    if ( 'mycpt' == $post->post_type ) {
        $url = site_url('/') . $post->post_name . '/';
    }

    return $url;
}
add_filter( 'post_type_link', 'change_mycpt_post_type_link', 10, 3 );

URLは正しくなりますが、機能しません。それらはページの書き換えルールを使用して解析され、404エラーを引き起こします(そのようなURLを持つページがないため)。しかし、それも修正できます。

function try_mycpt_before_page_in_parse_request( $wp ) {
    global $wpdb;

    if ( is_admin() ) return;

    if ( array_key_exists( 'name', $wp->query_vars ) ) {
        $post_name = $wp->query_vars['name'];

        $id = $wpdb->get_var( $wpdb->prepare(
            "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND post_name = %s ",
            'mycpt', $post_name
        ) );

        if ( $id ) {
            $wp->query_vars['mycpt'] = $post_name;
            $wp->query_vars['post_type'] = 'mycpt';
        }

    }
}
add_action( 'parse_request', 'try_mycpt_before_page_in_parse_request' );

PS。そのコードを使うのは賢いですか?それはまた別の質問です。それはWPの振る舞いをかなり大きな方法で変更するので、少しトリッキーかもしれません。しかし、本当に必要があるならば、あなたはこれをすることができます...

免責事項:このコードは非階層CPTに対してはうまく機能しますが、階層CPTに対しても適用できます。

1