プラグインでカスタム投稿タイプのカスタムアーカイブページを作成する


11

「my_plugin_lesson」という名前のカスタム投稿タイプを作成するプラグインを書いています。

$args = array (
    'public' => true,
    'has_archive' => true,
    'rewrite' => array('slug' => 'lessons', 'with_front' => false)
);
register_post_type ('my_plugin_lesson', $args);

カスタム投稿タイプにはアーカイブがあり、アーカイブのURLは次のとおりです。

http://example.com/lessons

このアーカイブの外観をカスタマイズしたい。標準のWordPressブログ投稿アーカイブではなく、表形式で投稿を一覧表示したい。archive-my_plugin_lesson.phpファイルを作成することで、テーマにカスタムアーカイブテンプレートを作成できることを理解しています。しかし、私はプラグインが任意のテーマで動作することを望みます。

テーマファイルを追加または変更せずにアーカイブページのコンテンツを変更するにはどうすればよいですか?

編集:archive_templateフィルターフックを 使用できることを理解しています。ただし、これはテーマテンプレートを置き換えるだけであり、テーマ固有である必要があります。たとえば、すべてのテーマのテンプレートが必要になりますちょうど約get_headerget_sidebarおよびget_footer機能を、しかし、コンテンツのIDが何をすべき<div>こと?これはテーマごとに異なります。

私がやりたいのは、コンテンツ自体を自分のコンテンツに置き換え、それをカスタム投稿タイプのアーカイブページの代わりに使用することです。

回答:


12

必要なのは、template_includeフィルターをフックしてプラグイン内にテンプレートを選択的に読み込むことです。

良い方法として、プラグインを配布する予定がある場合は、プラグインのバージョンを使用しない場合は、テーマに存在するarchive-my_plugin_lesson.phpかどうかを確認する必要がmyplugin/archive-lesson.phpあります。

この方法では、プラグインコードを編集せずに、テーマ(または子テーマ)を介してテンプレートをユーザーが簡単に置き換えることができます。

これは、1つの名前を言うために、WooCommmerceなどの一般的なプラグインで使用される方法です。

add_filter('template_include', 'lessons_template');

function lessons_template( $template ) {
  if ( is_post_type_archive('my_plugin_lesson') ) {
    $theme_files = array('archive-my_plugin_lesson.php', 'myplugin/archive-lesson.php');
    $exists_in_theme = locate_template($theme_files, false);
    if ( $exists_in_theme != '' ) {
      return $exists_in_theme;
    } else {
      return plugin_dir_path(__FILE__) . 'archive-lesson.php';
    }
  }
  return $template;
}

Codexの詳細


これはまだテーマのテンプレートファイルを置き換えるだけですよね?プラグインのarchive-lesson.phpファイルには何を入れますか?それぞれのテーマで作業するには、異なる必要があるでしょう。デフォルトの「20」のテーマでさえ、コンテンツを囲むdiv / sectionコンテナーが何であるかについて合意していません。
ベンミラー-モニカを覚えている

7

archive_templateフックを使用して、以下のスキームを使用することにより、テーマのアーカイブテンプレートのコンテンツを処理できますが、テンプレートは基本的に古いものを含むことができるので、そこにあるテーマの一部しか処理できないことは明らかです。

スキームは、テンプレートをフィルターの文字列($tpl_str)に読み込み、archive_templateコンテンツを置き換え、文字列を含め(トリックを使用eval( '?>' . $tpl_str );)、空のファイルを返してinclude「wp-includes / template-loader.php」をノーオペレーションになります。

以下は、プラグインで使用するコードのハッキングバージョンです。これは、使用する「クラシック」テンプレートを対象get_template_partとし、アーカイブよりも単一のテンプレートの処理に関心がありますが、始めるのに役立ちます。設定では、プラグインに「templates」というサブディレクトリがあり、空のファイル(「null.php」)とコンテンツテンプレート(「content-single-posttype1.php」、「content-archive-postype1.php」など)を保持しています。単一のケースのフォールバックテンプレート「single.php」と同様に、get_template_partこのディレクトリにあるカスタムバージョンを利用します。

define( 'MYPLUGIN_FOLDER', dirname( __FILE__ ) . '/' );
define( 'MYPLUGIN_BASENAME', basename( MYPLUGIN_FOLDER ) );

add_filter( 'single_template', 'myplugin_single_template' );
add_filter( 'archive_template', 'myplugin_archive_template' );

function myplugin_single_template( $template ) {
    static $using_null = array();

    // Adjust with your custom post types.
    $post_types = array( 'posttype1', );

    if ( is_single() || is_archive() ) {
        $template_basename = basename( $template );
        // This check can be removed.
        if ( $template == '' || substr( $template_basename, 0, 4 ) == 'sing' || substr( $template_basename, 0, 4 ) == 'arch' ) {
            $post_type = get_post_type();
            $slug = is_archive() ? 'archive' : 'single';
            if ( in_array( $post_type, $post_types ) ) {
                // Allow user to override.
                if ( $single_template = myplugin_get_template( $slug, $post_type ) ) {
                    $template = $single_template;
                } else {
                    // If haven't gone through all this before...
                    if ( empty( $using_null[$slug][$post_type] ) ) {
                        if ( $template && ( $content_template = myplugin_get_template( 'content-' . $slug, $post_type ) ) ) {
                            $tpl_str = file_get_contents( $template );
                            // You'll have to adjust these regexs to your own case - good luck!
                            if ( preg_match( '/get_template_part\s*\(\s*\'content\'\s*,\s*\'' . $slug . '\'\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE )
                            || preg_match( '/get_template_part\s*\(\s*\'content\'\s*,\s*get_post_format\s*\(\s*\)\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE )
                            || preg_match( '/get_template_part\s*\(\s*\'content\'\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE )
                            || preg_match( '/get_template_part\s*\(\s*\'[^\']+\'\s*,\s*\'' . $slug . '\'\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE ) ) {
                                $using_null[$slug][$post_type] = true;
                                $tpl_str = substr( $tpl_str, 0, $matches[0][1] ) . 'include \'' . $content_template . '\'' . substr( $tpl_str, $matches[0][1] + strlen( $matches[0][0] ) );
                                // This trick includes the $tpl_str.
                                eval( '?>' . $tpl_str );
                            }
                        }
                    }
                    if ( empty( $using_null[$slug][$post_type] ) ) {
                        // Failed to parse - look for fall back template.
                        if ( file_exists( MYPLUGIN_FOLDER . 'templates/' . $slug . '.php' ) ) {
                            $template = MYPLUGIN_FOLDER . 'templates/' . $slug . '.php';
                        }
                    } else {
                        // Success! "null.php" is just a blank zero-byte file.
                        $template = MYPLUGIN_FOLDER . 'templates/null.php';
                    }
                }
            }
        }
    }
    return $template;
}

function myplugin_archive_template( $template ) {
    return myplugin_single_template( $template );
}

カスタムget_template_part

/*
 * Version of WP get_template_part() that looks in theme, then parent theme, and finally in plugin template directory (sub-directory "templates").
 * Also looks initially in "myplugin" sub-directory if any in theme and parent theme directories so that plugin templates can be kept separate.
 */
function myplugin_get_template( $slug, $part = '' ) {
    $template = $slug . ( $part ? '-' . $part : '' ) . '.php';

    $dirs = array();

    if ( is_child_theme() ) {
        $child_dir = get_stylesheet_directory() . '/';
        $dirs[] = $child_dir . MYPLUGIN_BASENAME . '/';
        $dirs[] = $child_dir;
    }

    $template_dir = get_template_directory() . '/';
    $dirs[] = $template_dir . MYPLUGIN_BASENAME . '/';
    $dirs[] = $template_dir;
    $dirs[] = MYPLUGIN_FOLDER . 'templates/';

    foreach ( $dirs as $dir ) {
        if ( file_exists( $dir . $template ) ) {
            return $dir . $template;
        }
    }
    return false;
}

完全を期すために、カスタムを使用するフォールバック「single.php」を次に示しますget_template_part

<?php
get_header(); ?>

    <div id="primary" class="content-area">
        <div id="content" class="clearfix">
            <?php while ( have_posts() ) : the_post(); ?>

            <?php if ( $template = myplugin_get_template( 'content-single', get_post_type() ) ) include $template; else get_template_part( 'content', 'single' ); ?>

                <?php
                    // If comments are open or we have at least one comment, load up the comment template
                    if ( comments_open() || '0' != get_comments_number() ) :
                        comments_template();
                    endif;
                ?>

            <?php endwhile; ?>

        </div><!-- #content -->
    </div><!-- #primary -->

<?php get_sidebar(); ?>
<?php get_footer(); ?>

1

私は同じ質問を考えていました、そしてこれは私が思いついた仮想的な解決策です:

  • プラグイン内で、希望する方法でアーカイブループを出力するショートコードを作成します。
  • カスタム投稿タイプを作成するときは、「アーカイブ」オプションを有効にしないでください。
  • ループコンテンツのすべてのスタイルを制御するスタイルシートを追加します。

プラグインのアクティブ化時に、wp_insert_postを使用して、名前が投稿タイプで、コンテンツがショートコードであるページを作成します。

スタイルをさらに検討するためのオプションをショートコードに提供したり、テーマ固有のスタイルやカスタムスタイルに一致するクラスを投稿コンテナーに追加したりできます。ユーザーは、ページを編集して、ループの前/後にコンテンツを追加することもできます。


私はOPではありませんが、同じ問題の解決策を探していました。私はあなたの仮想ソリューションをたどりましたが、実際にそれが機能することを確認できました。
Lucio Crusca、2016年

いいね!これは誰かにとって便利でした。私はこれについて完全に忘れていました。
SkyShab 2016年

0

フィルターを使用できますsingle_templateコーデックスから取られた基本的な例:

function get_custom_post_type_template($single_template) {
     global $post;

     if ($post->post_type == 'my_post_type') {
          $single_template = dirname( __FILE__ ) . '/post-type-template.php';
     }
     return $single_template;
}

add_filter( "single_template", "get_custom_post_type_template" );

アーカイブテンプレートのフィルターフックはだと思いますがarchive_template、これが私がやろうとしていることにはうまくいかないと思います。詳細について質問を編集しました。
ベンミラー-モニカを思い出してください
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.