web-dev-qa-db-ja.com

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

"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 filterフックを使用できることを理解しています。しかし、これはテーマテンプレートを置き換えることだけです。テーマテンプレートはテーマ固有のものである必要があります。たとえば、ほぼすべてのテーマテンプレートにget_headerget_sidebar、およびget_footer関数が必要になりますが、コンテンツの<div>のIDは何になりますか。これはテーマごとに異なります。

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

7
Ben Miller

あなたが必要としているのはtemplate_includeフィルターをフックしてプラグインの中に選択的にあなたのテンプレートをロードすることです。

良い習慣として、あなたがあなたのプラグインを配布するつもりなら、あなたはarchive-my_plugin_lesson.php(あるいは多分myplugin/archive-lesson.php)がテーマの中に存在するかどうかをチェックするべきです。

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

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

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の詳細情報

8
gmazzap

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

スキームは、テンプレートを$tpl_strフィルタの文字列(archive_template)にロードし、あなたのコンテンツを置換し、(トリックeval( '?>' . $tpl_str );を使って)その文字列をインクルードし、そして "wp-includes/template-"のincludeが空ファイルを返すようにすることです。 loader.php "は何もしません。

以下は私がプラグインで使用するコードのハッキングバージョンです。これはget_template_partを使用し、アーカイブよりも単一のテンプレートの処理に関心がある「クラシック」テンプレートをターゲットにしていますが、始めるのに役立ちます。セットアップは、空のファイル( "null.php")とコンテンツテンプレート( "content-single-posttype1.php"、 "content-archive-postype1.php"など)を保持する "templates"というサブディレクトリをプラグインが持っていることです。単一のケースのためのフォールバックテンプレート "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;
}

完全を期すために、これはカスタムのget_template_partを使うフォールバック "single.php"です:

<?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(); ?>
6
bonger

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

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

プラグインを有効にしたら、wp_insert_postを使用して名前を投稿タイプ、内容をショートコードとしてページを作成します。

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

1
SkyShab

フィルタ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" );
0
Eyal