web-dev-qa-db-ja.com

同じ投稿に対する複数のパーマリンク

私は(i18nの理由で)同じ基礎となる投稿に対して複数のパーマリンクを持つことができるようにしたいです。

http://www.example.com/my-custom-post-type/this-is-a-cool-article
http://www.example.com/mon-type-de-poste-personnalise/cest-un-article-sympa

両方とも同じ投稿ページを指しています。組み込みのWP国際化関数は、投稿ページ自体の言語切り替えを処理します。私はSEOとエンドユーザーの美学の両方のためのURL表示にもっと関心があります。

ブラウザのURLを変更したくないため、301リダイレクトを使用できません。カスタムポストタイプのスラッグを国際化する方法は理解できますが、実際のポストスラッグは国際化できません。

二次投稿スラッグを投稿メタフィールドに保存できると思いますが、有効にするにはルーティングのどこかにフックする必要があります。これに対処するための場所、またはこれに対処するためのより簡単な方法はありますか。

2
Roscius

リクエストの解析はWP::parse_request()で処理されます。その後、wpオブジェクトのインスタンスを与えるアクションフックparse_requestがあります。

我々はhttp://www.example.com/my-custom-post-type/this-is-a-cool-articleがあなたのパーマリンクであり、http://www.example.com/mon-type-de-poste-personnalise/cest-un-article-sympaが404で終わると仮定します。それであなたのコールバックをチェックインする最初の事はwpオブジェクトがエラー/ 404状態にあるならば、あるべきです:

if ( ! empty( $wp->query_vars[ 'error' ] && 404 == $wp->query_vars[ 'error' ] ) {
    //…
}

編集:私は間違いを犯した:それは$wpステータスがあなたのエイリアスURL上で常に404であることは確かではない。それはあなたのシステムの書き換え規則に強く依存します。だからあなたは直接あなたの別名cpt slugをチェックする必要があります。

これで、リクエストを自分で解析し、対応する投稿を見つけるためにメタ値を検索する必要があります。

if ( ! empty( $wp->query_vars[ 'error' ] && '404' == $wp->query_vars[ 'error' ] ) {

    //look up for your post, this var should looks like 
    // 'mon-type-de-poste-personnalise/cest-un-article-sympa' in your case:
    $wp->request;
    //e.g.
    $parts = explode( '/', $wp->request );
    // your language slug
    $slug = ( isset( $parts[ 1 ] ) ) ? $parts[ 1 ] : '';
    // do your query with your meta value $slug here

}

次に、$wp->query_varsを元のリクエストに直面したときのように設定します。

if ( ! empty( $wp->query_vars[ 'error' ] && '404' == $wp->query_vars[ 'error' ] ) {

    //look up for your post, this var should looks like 
    // 'mon-type-de-poste-personnalise/cest-un-article-sympa' in your case:
    $wp->request;
    //e.g.
    $parts = explode( '/', $wp->request );
    // your i18n post slug
    $slug = ( isset( $parts[ 1 ] ) ) ? $parts[ 1 ] : '';
    // do your query with your meta value $slug here
    // and setup the WP_Post object for the matching post
    $matching_post; // WP_Post

    // if you don't find any post, return here!

    // unset the error flag
    unset( $wp->query_vars[ 'error' ] );

    // your cpt slug
    $cpt_slug = 'my-custom-post-type';

    $wp->query_vars[ $cpt_slug ] = $matching_post->post_name;
    $wp->query_vars[ 'post_type' ] = $cpt_slug;
    $wp->query_vars[ 'name' ] = $matching_post->post_name;
}

最後にやらなければならないことは、WordPressがredirect_canonicalアクションから関数template_redirectを削除することによって、正規のURLに自動的にリダイレクトしないようにすることです。

if ( ! empty( $wp->query_vars[ 'error' ] && '404' == $wp->query_vars[ 'error' ] ) {

    //look up for your post, this var should looks like 
    // 'mon-type-de-poste-personnalise/cest-un-article-sympa' in your case:
    $wp->request;
    //e.g.
    $parts = explode( '/', $wp->request );
    // your language slug
    $slug = ( isset( $parts[ 1 ] ) ) ? $parts[ 1 ] : '';
    // do your query with your meta value $slug here
    // and setup the WP_Post object for the matching post
    $matching_post; // WP_Post

    # unset the error flag
    unset( $wp->query_vars[ 'error' ] );

    # your cpt slug
    $cpt_slug = 'my-custom-post-type';

    $wp->query_vars[ $cpt_slug ] = $matching_post->post_name;
    $wp->query_vars[ 'post_type' ] = $cpt_slug;
    $wp->query_vars[ 'name' ] = $matching_post->post_name;

    # don't redirect to the canonical url
    remove_action( 'template_redirect', 'redirect_canonical' );
}

最後のコードブロックを関数に入れて、それをparse_requestアクションに適用します。

add_action( 'parse_request', 'wpse_126309_parse_request' );

/**
 * @wp-hook parse_request
 * @param WP $wp
 * @return void
 */
function wpse_126309_parse_request( $wp ) {
    // the code goes here
}

この(概念の証明にすぎません)を副作用についてテストする必要があります。

3
David