web-dev-qa-db-ja.com

カスタム投稿タイプにテンプレートを適用

今日、私は各ページとセクション内のカスタムテンプレートを欲しているクライアントを得ました。私はLaravel custom sh3tを提案しましたが、彼はWordPressを望んでいました。メインのほうが簡単なようです(私の経験からではありません)。

.. ここまでは順調ですね。私は少し混乱しています。

そのため、私は自分の親エンティティをページにすることにしたので、各ページに異なるテンプレートを適用できます。それから私はこのページの中にハードコアではないはずのセクションを持っています。ユーザーはセクションレイアウト(template)を選択し、現在のページ内のセクションを削除または並べ替えることができます。そして最後に、彼らがウェブサイトで最も小さい実体であるので私はポストを持っています。投稿はブートストラップ(col-md-2、col-lg-6)などのように列として表示されます。

セクションとして使用するカスタム投稿タイプを作成することにしましたが、投稿タイプにテンプレートを含めることはできず、ページにのみ投稿タイプを含めることができます。これは私の計画をこれまで妥協し、解決策の調査に5時間費やしました(no exit)。だから私はこれを行うための別の戦略が必要です。 2つのエンティティ用のテンプレートが必要です。

誰かがこの問題の解決策を提案することはできますか? (ビールを買います!

編集:

独自のカスタム投稿タイプを作成するには、ワードプレスで'カスタム投稿タイプUI'のプラグインを使用します。もちろん、短いコードスニペットをfunctions.phpファイルに貼り付けることで別の方法がありますが、ここでは説明しません。

1
Dimitrov

通常、私は@Miloがこのような投稿を提供したような強い答えには従いません。私はすでに他のプロジェクトのためにこのコードを書いていたので、私は共有したいと思った。

以下のコードは@Miloが彼の答えで要約したすべてをします、そして私は前にこれを大成功で成功させました。

これが何が起こっているのかのチートシートです。

1) 'add_meta_boxes'アクションにフックして、編集画面に新しいカスタムメタボックスをレンダリングします(ネイティブの 'page'投稿タイプを除く)。

2) 'admin_menu'アクションにフックして、既存の 'Page Attributes'メタボックスを削除します(ネイティブの 'page'投稿タイプを除く)。

3)カスタムのメタボックスを作成して、ネイティブの「ページ属性」メタボックスの機能を置き換えます。これには、初期化したカスタム投稿タイプのPARENT、TEMPLATE、およびORDERを定義するためのフィールドが含まれます。

4) 'save_post'アクションにフックしてあなたのテンプレートの選択を投稿メタに保存します。

5)デフォルトのWordPressテンプレートの代わりにカスタムテンプレートをロードするために 'single_template'フィルタに接続します。

これはあなたのための完全に機能的なコピー/貼り付けです。

/** Custom Post Type Template Selector **/
function cpt_add_meta_boxes() {
    $post_types = get_post_types();
    foreach( $post_types as $ptype ) {
        if ( $ptype !== 'page') {
            add_meta_box( 'cpt-selector', 'Attributes', 'cpt_meta_box', $ptype, 'side', 'core' );
        }
    }
}
add_action( 'add_meta_boxes', 'cpt_add_meta_boxes' );

function cpt_remove_meta_boxes() {
    $post_types = get_post_types();
    foreach( $post_types as $ptype ) {
        if ( $ptype !== 'page') {
            remove_meta_box( 'pageparentdiv', $ptype, 'normal' );
        }
    }
}
add_action( 'admin_menu' , 'cpt_remove_meta_boxes' );

function cpt_meta_box( $post ) {
    $post_meta = get_post_meta( $post->ID );
    $templates = wp_get_theme()->get_page_templates();

    $post_type_object = get_post_type_object($post->post_type);
    if ( $post_type_object->hierarchical ) {
        $dropdown_args = array(
            'post_type'        => $post->post_type,
            'exclude_tree'     => $post->ID,
            'selected'         => $post->post_parent,
            'name'             => 'parent_id',
            'show_option_none' => __('(no parent)'),
            'sort_column'      => 'menu_order, post_title',
            'echo'             => 0,
        );

        $dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post );
        $pages = wp_dropdown_pages( $dropdown_args );

        if ( $pages ) { 
            echo "<p><strong>Parent</strong></p>";
            echo "<label class=\"screen-reader-text\" for=\"parent_id\">Parent</label>";
            echo $pages;
        }
    }

    // Template Selector
    echo "<p><strong>Template</strong></p>";
    echo "<select id=\"cpt-selector\" name=\"_wp_page_template\"><option value=\"default\">Default Template</option>";
    foreach ( $templates as $template_filename => $template_name ) {
        if ( $post->post_type == strstr( $template_filename, '-', true) ) {
            if ( isset($post_meta['_wp_page_template'][0]) && ($post_meta['_wp_page_template'][0] == $template_filename) ) {
                echo "<option value=\"$template_filename\" selected=\"selected\">$template_name</option>";
            } else {
                echo "<option value=\"$template_filename\">$template_name</option>";
            }
        }
    }
    echo "</select>";

    // Page order
    echo "<p><strong>Order</strong></p>";
    echo "<p><label class=\"screen-reader-text\" for=\"menu_order\">Order</label><input name=\"menu_order\" type=\"text\" size=\"4\" id=\"menu_order\" value=\"". esc_attr($post->menu_order) . "\" /></p>";
}

function save_cpt_template_meta_data( $post_id ) {

    if ( isset( $_REQUEST['_wp_page_template'] ) ) {
        update_post_meta( $post_id, '_wp_page_template', $_REQUEST['_wp_page_template'] );
    }
}
add_action( 'save_post' , 'save_cpt_template_meta_data' );

function custom_single_template($template) {
    global $post;

    $post_meta = ( $post ) ? get_post_meta( $post->ID ) : null;
    if ( isset($post_meta['_wp_page_template'][0]) && ( $post_meta['_wp_page_template'][0] != 'default' ) ) {
        $template = get_template_directory() . '/' . $post_meta['_wp_page_template'][0];
    }

    return $template;
}
add_filter( 'single_template', 'custom_single_template' );
/** END Custom Post Type Template Selector **/

私がここで行った唯一の仮定は、あなたのテンプレートは以下の命名規則のベストプラクティスに従うということです。

posttype-templatename.php

例として、テーマ内で次の命名規則を使用して「イベント」カスタム投稿タイプのカスタムテンプレートを定義できます。

event-standard.php
event-allday.php
event-recurring.php

このコードは、 "イベント"テンプレートをイベント投稿タイプに適用することのみを許可するのに十分スマートです。言い換えれば、 "section-video.php"テンプレートと呼ばれるテンプレートは、イベント投稿タイプには表示されません。そのテンプレートは、代わりに "Section"投稿タイプのオプションとして表示されます。

この機能を削除するには、上記のコードから条件付きロジックを削除するだけです。

if ( $post->post_type == strstr( $template_filename, '-', true) ) {  }
5
dswebsme

WordPress 4.7では、複数のテンプレートのサポートがカスタム投稿タイプに与えられました。

カスタム投稿タイプでテンプレートを利用できるようにするには、テンプレートファイルのメタ部分にこのヘッダーを追加します。

Template Post Type: post, foo, bar 

たとえば、カスタム投稿タイプに「my_events」というラベルが付いているとします。「全角」というテンプレートをPagesとカスタム投稿タイプの両方で使用できるようにします。

これ:

/**
 * Template Name: Fullwidth
 * 
 * Template Description...
 **/

これになる:

/**
 * Template Name: Fullwidth
 * Template Post Type: page, my_events
 * 
 * Template Description...
 **/

もっと詳しく: 4.7の投稿タイプテンプレート from WordPress Core

13

カスタム投稿タイプは選択可能なテンプレートを持つことができます、あなたはそれらをあなた自身で実装する必要があるでしょう。 WordPressがページの投稿タイプを使って内部的に行う方法は、テンプレートスラッグを投稿メタデータに保存してから、 階層 に従ってテンプレートがフロントエンドにロードされたときに値が存在するかどうかを確認することです。

基本的なプロセスは、 メタボックス をカスタム投稿タイプに追加してユーザーにテンプレートを選択させることです(リストを作成するには get_page_templates を使用します)。

2番目のステップは single_template にフィルタを追加して、そのオブジェクトがフロントエンドで表示されているときに選択されたテンプレートをロードすることです。

wp-includes/template.phpwp-includes/post-template.phpのコアファイルを見れば、WordPressが使用しているコード(およびフィルタが適用されている場所)を確認でき、それをニーズに合わせて調整できます。 get_queried_objectは、フィルタ内のオブジェクトのpost_typeと、投稿のメタデータを取得できるようにするためのIDを提供します。

編集 -

これは、メタキーmy_templateにあるもの(whatever.phpのようなもの)をロードするpost投稿タイプのためのサンプルフィルタです。新しい投稿を作成し、ネイティブのカスタムフィールドメタボックスを使用してそのキーの下にファイル名を入力することでテストできます。これはあなたのカスタムタイプ('post'を変更)に合わせて変更することができ、ファイルを保存したり名前を付けたりするためにあなたが使っているどんな方式でも変更することができます。

function wpd_post_type_template( $template ){
    $object = get_queried_object();
    if( ! empty( $object->post_type )
        && 'post' == $object->post_type
        && $slug = get_post_meta( $object->ID, 'my_template', true ) ){
        if( $custom_template = locate_template( $slug, false ) ){
            $template = $custom_template;
        }
    }
    return $template;
}
add_filter( 'single_template', 'wpd_post_type_template' ) ;
1
Milo