web-dev-qa-db-ja.com

ACFフィールドに基づいてパーマリンクを作る

これは、「どうすればよいのか」という質問であり、「やればいいのですか」ということです。

私はACFが多いサイトを持っています、そこで私はACFフィールドの一つに基づいてパーマリンクを作りたいです(それをfooと呼びましょう)。 foo-フィールドの値が123であれば、そのページへのパーマリンクをhttp://example.org/s123にします(sはパーマリンク内のpost-idとの衝突を避けるためです)。そのURLを取得した場合は、http://example.org/s123-1などと呼ぶ必要があります。

ACFフィールドはカスタム投稿タイプに設定されています。そしてこのサイトには重要な情報がいくつか含まれているので、プラグインを使用するのではなく、この機能を除外したいと思います。それで、それはfunctions.php-ファイルに入るものである必要があります。

これは可能ですか?そしてWordPressのパーマリンク構造(permalink-settings-pageで許可されているもの以外)を台無しにするのは賢明ではないですか?

加算

CPTに「ルート」パーマリンクを設定すると、 投稿とページのパーマリンクは解除されます となります。 : - /

... CPTにNice/simpleパーマリンクを持たせるのがこれほど難しいということは知りませんでした。

3
Zeth

CFから作られたURL

さて、あなたはこれを多くの方法で行うことができます...それらの1つはparse_requestフィルタを使用してその振る舞いを修正することでしょう、しかしそれは何かを簡単にめちゃくちゃにすることができます。

別の方法はsave_postアクションを使って投稿post_nameを修正することです。そのためWordPressは通常通りに動作しますが、post_nameはタイトルではなくカスタムフィールドに基づいて生成されます。これが解決策です。どうして?リンクが一意であることを確認するためにWP関数を使用することができます。

だからここにコードがあります:

function change_post_name_on_save($post_ID, $post, $update ) {
    global $wpdb;

    $post = get_post( $post_ID );
    $cf_post_name = wp_unique_post_slug( sanitize_title( 's' . get_post_field('foo', $post_ID), $post_ID ), $post_ID, $post->post_status, $post->post_type, $post->post_parent );

    if ( ! in_array( $post->post_status, array( 'publish', 'trash' ) ) ) {
        // no changes for post that is already published or trashed
        $wpdb->update( $wpdb->posts, array( 'post_name' => $cf_post_name ), array( 'ID' => $post_ID ) );
        clean_post_cache( $post_ID );
    } elseif ( 'publish' == $post->post_status ) {
        if ( $post->ID == $post->post_name ) {
            // it was published just now
            $wpdb->update( $wpdb->posts, array( 'post_name' => $cf_post_name ), array( 'ID' => $post_ID ) );
            clean_post_cache( $post_ID );
        }
    }
}
add_action( 'save_post', 'change_post_name_on_save', 20, 3 );

ACFフィールドは投稿の後に保存されるので、これは最も美しいものではありません。そのため、投稿が既に保存された後でpost_nameを上書きする必要があります。しかし、それはちょうどうまくいくはずです。

ルートのCPT

そして、あなたの質問の2番目の部分があります:CPTスラグなしでCPT URLを作る方法...

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

これは私が読んでいることを単純化しすぎているのかもしれませんが、パーマリンクを制御するのにACFフィールドを使うよりはむしろURLのパーマリンクを修正するのが最も簡単なことです。プログラムで行うよりも。

これがもっと複​​雑な場合は、 WP_Rewrite API を見て、それを使ってカスタムロジックを作成します。

また、 パーマリンク構造を書き換えることができます / CPT宣言で

0
DevLime