web-dev-qa-db-ja.com

カスタム投稿タイプの投稿を静的フロントページとして設定する方法

カスタムテーマを最初から作成していますが、カスタム投稿タイプが 'my_frontpage'で、そのうちの1つをフロントページとして宣言します。私はadmin経由でこれを行いたいので、単純に Front Page 外観のカスタマイズ>>静的フロントページ の選択ボックスに私のcptを追加します。

この問題はインターネットでかなり数回議論されています。しかし、その目標を達成するためのすべての手順を包括的に説明する方法を見つけることができませんでした。

これまでのところ、私は私のcptからの投稿で利用可能なフロントページ 'pages'の選択肢を広げるためにある種のフックを使う必要があることを理解しています。しかし、どちらのフックを使うべきですか?アクションやフィルタフックを使用する必要があるかどうかさえわかりませんか?それでは、誰かがこの問題を素人の言葉で案内してくれませんか。

私が見つけた最も近い結果は この質問 でした。しかし、私はまだ完全にそこで何が起こるのか理解することができていません...

3
Bunjip

私はあなたの問題と options-reading.php ページを見る時間がありました。これはバックエンドで読書設定ページをレンダリングするのに使用されるテンプレートです。

残念ながら、選択可能なドロップダウンでスティッキポストとしてカスタム投稿をフィルタリングまたは追加するためのフィルタはありません。 2つの隠しフィルタがありますが、それを使うことができます。

私見、私はここでget_pagesがより良い選択肢だと思います。このようにして、wp_dropdown_pages()にすべてのマークアップを引き受けさせます。 get_pagesフィルタを使用するときは注意が必要です。

  • 管理領域、特に閲覧設定ページのみをターゲットにしていることを確認する必要があります。それ以外の場合は、get_pages()関数を使用するすべての機能/ページを変更します。

カスタム投稿タイプの投稿と共に表示するページが必要か、カスタム投稿タイプのみが必要かを決定する必要があります。

あなたは以下を試すことができます:

add_filter( 'get_pages', function ( $pages, $args )
{
    // First make sure this is an admin page, if not, bail
    if ( !is_admin() )
        return $pages;

    // Make sure that we are on the reading settings page, if not, bail
    global $pagenow;
    if ( 'options-reading.php' !== $pagenow )
        return $pages;

    // Remove the filter to avoid infinite loop
    remove_filter( current_filter(), __FUNCTION__ );

    $args = [
        'post_type'      => 'my_frontpage',
        'posts_per_page' => -1
    ];
    // Get the post type posts with get_posts to allow non hierarchical post types
    $new_pages = get_posts( $args );    

    /**
     * You need to decide if you want to add custom post type posts to the pages
     * already in the dropdown, or just want the custom post type posts in
     * the dropdown. I will handle both, just remove what is not needed
     */
    // If we only need custom post types
    $pages = $new_pages;

    // If we need to add custom post type posts to the pages
    // $pages = array_merge( $new_pages, $pages );

    return $pages;
}, 10, 2 );

カスタム投稿タイプの投稿がドロップダウンに表示されます。注意してください、このコードはブログページのドロップダウンにも影響します。

これを回避するには、静的カウンタを使用して、フィルタが実行された回数を数え、その後フィルタがブログページのドロップダウンに適用される直前にベイルすることができます。 get_pages()が3回実行されると、フィルターは合計3回実行されます。

  • 最初に、静的フロントページとして設定するページが実際にあるかどうかを確認します。

  • 2回目の実行は静的フロントページドロップダウンで使用されるwp_dropdown_pages()内になります。

  • 最後の実行は、ブログページのドロップダウンで使用されるwp_dropdown_pages()内になります。

だから、これに基づいて、私たちは試すことができます

add_filter( 'get_pages', function ( $pages, $args )
{
    // First make sure this is an admin page, if not, bail
    if ( !is_admin() )
        return $pages;

    // Make sure that we are on the reading settings page, if not, bail
    global $pagenow;
    if ( 'options-reading.php' !== $pagenow )
        return $pages;

    // Remove the filter to avoid infinite loop
    remove_filter( current_filter(), __FUNCTION__ );

    // Setup our static counter
    static $counter = 0;

    // Bail on the third run all runs after this. The third run will be 2
    if ( 2 <= $counter )
        return $pages;

    // Update our counter
    $counter++;

    $args = [
        'post_type'      => 'my_frontpage',
        'posts_per_page' => -1
    ];
    // Get the post type posts with get_posts to allow non hierarchical post types
    $new_pages = get_posts( $args );    

    /**
     * You need to decide if you want to add custom post type posts to the pages
     * already in the dropdown, or just want the custom post type posts in
     * the dropdown. I will handle both, just remove what is not needed
     */
    // If we only need custom post types
    $pages = $new_pages;

    // If we need to add custom post type posts to the pages
    // $pages = array_merge( $new_pages, $pages );

    return $pages;
}, 10, 2 );

フロントエンドにアクセスしてフロントページにアクセスすると、単一の投稿ページにリダイレクトされることがわかります。これは、デフォルトでは静的フロントページのメインクエリがpage投稿タイプをクエリするように設定されているためです。これにより404が返され、redirect_canonical()は単一の投稿ページにリダイレクトします。これは簡単に解決できます。静的フロントページのメインクエリーを調整するだけです。

add_action( 'pre_get_posts', function ( $q )
{
    if (    !is_admin() // Only target the front end
         && $q->is_main_query() // Only target the main query
         && 'page' === get_option( 'show_on_front' ) // Only target the static front page
    ) {
        $q->set( 'post_type', 'my_frontpage' );
    }
});

静的フロントページが正しく表示されます。

あとはテンプレートを設定するだけです。 front-page.phpを作成するだけで、WordPressが自動的にそれを使用します

2
Pieter Goosen

ページテンプレートを使用せずに、正しい投稿タイプのテンプレートを使用してフロントページにWordpressを読み込ませる方法もあります。フロントページを単一の投稿自体と同じように見せたい場合は、コードの重複を避けるのに役立ちます。

add_filter( 'template_include', 'add_front_page_template_path', 10, 1);

function add_front_page_template_path( $template_path ) {
    if (
        is_front_page() 
        && get_option( 'show_on_front' ) == 'page' 
        && ( $post_id = get_option( 'page_on_front' ) )
        && ( $post_type = get_post_type( $post_id ) ) != 'page' 
    ) {
        $_template_path = get_single_template( $post_type );

        /* In case there’s no template */
        $template_path = ( $template_path == '' ) ? $template_path : $_template_path;
    }

    return $template_path;  
}
0
cruzquer

Pieterが疑いなくエレガントかつ包括的に問題を解決した一方で、私はついに別の解決策を講じました。それもここで共有したいと思います。たぶん何人かの人々は来る時間の間に同じような問題に直面しています。

私の質問で説明されているようなカスタム投稿タイプ定義のために、私は Pods と呼ばれるプラグインを使いました。プラグインの開発者やコミュニティはカスタムの投稿タイプを定期的に処理している可能性が高いので、私は彼らのサポートチャンネルで私の質問をすることが役に立つかもしれないと思いました。

Pods開発チームの方からとても親切な人でした。そのため、高度に個別の静的フロントページを作成する目的でカスタム投稿タイプを定義するのではなく、カスタムページを標準ページに追加することをお勧めします。これがフロントページになります。それが私が私の目標を達成するためにしたことであり、それは私が他のユーザーにも推奨するものです。

データモデリングの観点からは、完全なデータ型を定義する必要はありません。たとえば、クラス、単一の項目にのみ適用する場合(クラスの場合は単一のフロントページ)。 Advanced Custom Fields という別のプラグインを使用しました。これは、Wordpressが用意している以上に、カスタムフィールドに高度なデータ型を使用できるためです。 functions.phpを使ってカスタムフィールドを追加することもできます。願っています、それが役立ちます。

0
Bunjip