私はWordPressプラグインでカスタム投稿タイプpaper
を定義しています。これはメインのクエリで標準の投稿と一緒に表示されます。
function add_custom_post_types_to_query( $query ) {
if ( is_home() && $query->is_main_query() )
$query->set( 'post_type', array( 'post', 'paper' ) );
// As was pointed out by Ihor Vorotnov this return is not necessary.
// return $query;
}
add_action( 'pre_get_posts', 'add_custom_post_types_to_query' );
以下の方法で、私の投稿タイプ用のカスタムsingle-paper.php
テンプレートをプラグインディレクトリから登録することもできました。
function get_custom_post_type_single_template( $single_template ) {
global $post;
if ( $post->post_type == 'paper' ) {
$single_template = dirname( __FILE__ ) . '/single-paper.php';
}
return $single_template;
}
add_filter( 'single_template', 'get_custom_post_type_single_template' );
私の投稿がメインクエリに表示される方法を制御するために、私のテーマ(onepress
)で使用されるcontent-____.php
テンプレートに似たようなことをしたいと思います。
テーマのindex.php
はさらに言っています:
<?php /* Start the Loop */ ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php
/*
* Include the Post-Format-specific template for the content.
* If you want to override this in a child theme, then include a file
* called content-___.php (where ___ is the Post Format name) and that will be used instead.
*/
get_template_part( 'template-parts/content', get_post_format() );
?>
<?php endwhile; ?>
しかし、私はむしろこのために子テーマを実装したくないし、プラグインのカスタム投稿タイプに関連するすべてのコードを残しておきたいです。
get_template_part( 'template-parts/content', get_post_format() );
が私のプラグインが提供するカスタムテンプレートをpaper
投稿用に、テーマの標準テンプレートを通常の投稿用に使用するようなフィルタを追加する方法はありますか?
私は'single_template'
に対して上記で使用したコードのさまざまなバリエーションを試しましたが、役に立ちません。
残念ながら get_template_part()
functionはあなたが望むものを達成するのに適したフィルタを持っていません。 get_template_part_{$slug}
アクションフックを使ってテンプレート部分を挿入することは可能ですが、あなたのテーマや子テーマを変更することなく、とにかく元のテンプレート部分が追加されます。そのため、この方法で既存のテンプレートパーツを置き換えることはできません。
ただし、以下のいずれかの方法で目的の結果を得ることができます。
paper
カスタム投稿タイプのスタイルを変更したいだけの場合は、WordPressによって生成されたCSSクラスを使用することができます。 WordPressのどの標準テーマでも、投稿コンテンツ用の$post_type
およびtype-{$post_type}
CSSクラスが生成されます。たとえば、カスタム投稿タイプpaper
にはpaper
とtype-paper
のCSSクラスがあり、一般的なpost
にはpost
とtype-post
のCSSクラスがあります。またホームページの本文にはhome
CSSクラスがあります。そのため、ホームページのpaper
エントリをターゲットにするには、次のCSSルールを使用します。
body.home .type-paper {
/* Custom CSS for paper entries in the home page */
}
デフォルトのCSSクラスでは不十分な場合は、プラグインの post_class
filterフックを使用してCSSクラスを変更(追加/削除)することもできます。このような:
add_filter( 'post_class', 'paper_post_class' );
function paper_post_class( $class ) {
if ( get_post_type() === 'paper' && is_home() ) {
// remove these classes
$remove = array( 'css-class-to-remove', 'another-class-to-remove' );
$class = array_diff( $class, $remove );
// add these classes
$add = array( 'custom-paper', 'my-paper-class' );
$class = array_merge( $add, $class );
}
return $class;
}
このようにして、テーマファイルを変更することなく、paper
エントリに不要なCSSクラスを削除し、paper
エントリに必要な新しいCSSクラスを追加することができます。それから、それらのCSSクラスを使用して、必要に応じてpaper
エントリのスタイルを変更します。
CSSクラスをターゲットにしただけではスタイルを変更できない場合は、プラグインからテンプレート部分を変更することもできます。ただし、get_template_part()
によって追加されたテンプレート部分をフックを使用して置き換えることはできないため、プラグイン内からget_template_part()
呼び出しを変更できるようにテンプレートを変更する必要があります。
これを行うには、pre_get_posts
フック関数をターゲットにして、 template_include
filterフックを使用して、以下のようにホームページテンプレートを変更します。
function add_custom_post_types_to_query( $query ) {
if ( is_home() && $query->is_main_query() ) {
$query->set( 'post_type', array( 'post', 'paper' ) );
// now also change the home page template, but only when this condition matches
add_filter( 'template_include', 'wpse258844_custom_template', 999 );
}
}
add_action( 'pre_get_posts', 'add_custom_post_types_to_query' );
その後、次のコードを使用します(必要に応じて変更します)。
// for better file management, use a separate "theme-{$theme_name_slug}" directory within your plugin directory
// so if the active theme name is "OnePress", the directory name will be "theme-onepress"
// This will save you a ton of headache if you change the theme,
// as different themes may use different function calls within the templates, which other themes may not have
define( 'wpse258844_TEMPLATE_DIR', plugin_dir_path( __FILE__ ) . sprintf( 'theme-%s/', sanitize_title( wp_get_theme() ) ) );
function wpse258844_custom_template( $template ) {
// this file will replace your homepage template file
$index_paper = wpse258844_TEMPLATE_DIR . 'custom-home.php';
// file_exists() check may need clearing stat cache if you change file name, delete the file etc.
// Once you are done, comment out or remove clearstatcache(); in production
clearstatcache();
if ( file_exists( $index_paper ) ) {
$template = $index_paper;
}
return $template;
}
function wpse258844_get_template_part( $slug, $name = null ) {
if( get_post_type() === 'paper' ) {
// just to be consistant with get_template_part() function
do_action( "get_template_part_{$slug}", $slug, $name );
$located = '';
$name = (string) $name;
// file_exists() check may need clearing stat cache if you change file name, delete the file etc.
// Once you are done, comment out or remove clearstatcache(); in production
clearstatcache();
if ( '' !== $name && file_exists( wpse258844_TEMPLATE_DIR . "{$slug}-{$name}.php" ) ) {
$located = wpse258844_TEMPLATE_DIR . "{$slug}-{$name}.php";
}
else if ( file_exists( wpse258844_TEMPLATE_DIR . "{$slug}.php" ) ) {
$located = wpse258844_TEMPLATE_DIR . "{$slug}.php";
}
if ( '' != $located ) {
load_template( $located, false );
return;
}
}
get_template_part( $slug, $name );
}
プラグインに上記のCODEがあれば(CODE内のコメントを読んでください):
テーマテンプレートファイルを保存するために、プラグインディレクトリ内に新しいディレクトリを作成します。 theme-onepress
。あなたが異なるテーマでデザイン変更をテストしたいなら、これは将来あなたを助けるでしょう(私はそれがこれらすべての混乱の主な目的だと思います;)。
新しいtheme-onepress
ディレクトリ内に、custom-home.php
という名前のファイルを作成します。あなたのテーマからホームページテンプレートのコードをコピーします(index.php
、home.php
、またはあなたのテーマがホームページテンプレートに使っているものはなんでも)。
custom-home.php
で、get_template_part
のすべての呼び出しをwpse258844_get_template_part
に変更します。パラメータを変更する必要はなく、関数名だけです。上記のCODEのwpse258844_get_template_part()
関数はget_template_part()
関数と同じで、カスタムテンプレートパーツがプラグインのtheme-{$theme_name_slug}
(例えばtheme-onepress
)ディレクトリ内に見つからない場合はデフォルトの動作に戻ります。
最後に、あなたのプラグインのtheme-{$theme_name_slug}
ディレクトリで置き換えたいテンプレート部品ファイルを置き換えます。
たとえば、元の呼び出しがget_template_part( 'template-parts/content', get_post_format() )
で、content.php
テンプレート部分を置き換えたい場合は、単にcontent.php
という名前のファイルをプラグインのtheme-onepress/template-parts
ディレクトリに配置します。つまり、theme-onepress
ディレクトリはテンプレートパーツの子テーマのように動作します。つまり、単純なドロップイン置換です。
それのためにあなた自身の関数を作成してください:
function get_template_part_custom($content_name) {
global $post;
//its paper type?
if ($post->post_type == 'paper') {
//get template-parts/content-paper.php
get_template_part( 'template-parts/content', $content_name );
}else{
//fallback to the default
get_template_part( 'template-parts/content', get_post_format($post) );
}
}
このように使用してください。
get_template_part_custom('paper');
投稿がpaper
型の場合、ルートテーマフォルダのcontent-paper.php
というフォルダ内にtemplate-parts
というファイルをロードしようとします。ファイルが存在しない場合は、content.php
をロードしようとします、 template-hierarchy を確認します。私はあなたがあなたのテンプレートを登録する必要があるとは思わないsingle-paper.php
、WordPressはあなたのためにそれを拾います。
編集:
プラグインからテンプレートを読み込むには:
//load a custom file from the plugin
add_filter( 'template_include', 'return_our_template');
//Returns template file
function return_our_template( $template ) {
// Post ID
$post_id = get_the_ID();
// For all other Types that arent ours
if ( get_post_type( $post_id ) != 'paper' ) {
return $template;
}
// Else use our custom template
if ( is_single() ) {
return get_custom_template( 'single' );
}
}
//Get the custom template if is set
function get_custom_template( $template ) {
// Get the slug
$template_slug = rtrim( $template, '.php' );
$template = $template_slug . '.php';
// Check if a custom template exists in the theme folder, if not, load the plugin template file
if ( $theme_file = locate_template( array( 'plugin_template/' . $template ) ) ) {
$file = $theme_file;
}
else {
//here path to '/single-paper.php'
$file = PATH_TO_YOUR_BASE_DIR . $template;
}
//create a new filter so the devs can filter this
return apply_filters( 'filter_template_' . $template, $file );
}
私がソースコードから見ることができる限り、あなたが通常するようにあなたはget_template_part()
をフィルターにかけることができません。 このスレッド を見てください。
これは、求められたことを達成するためのもう1つの「ハック」です。
カスタム投稿タイプ用のカスタムテンプレートを使用するためにpost format
(post type
!と混同しないでください)を使用することができます。行を覚えて
get_template_part( 'template-parts/content', get_post_format() );
質問に記載されているindex.php
に。この構造を通して、ほとんどの標準テーマはpost format
に応じて異なるテンプレートをロードします。
paper
name__などの特定のカスタム投稿タイプの投稿はすべて、特定の投稿形式、たとえばaside
name__を持つことができます。
set_post_format( $post_id, 'aside' )
関数が'save_post'
フックにフックされていて、以下のようなものを追加することによって
function paper_format_terms( $terms, $post_id, $tax ) {
if ( 'post_format' === $tax && empty( $terms ) && 'paper' === get_post_type( $post_id ) ) {
$aside = get_term_by( 'slug', 'post-format-aside', $tax );
$terms = array( $aside );
}
return $terms;
}
add_filter( 'get_the_terms', 'paper_format_terms', 10, 3 );
'get_the_terms'
フックに。
カスタム投稿フォーマットを定義することはできませんが、通常、他には使用されない投稿フォーマットが少なくとも1つあります。 'aside'形式は良い選択です。
標準のテーマは、paper
name__の投稿に遭遇したときはいつでもテンプレート.../template-parts/content-aside.php
を探します。やらなければいけないことは、テーマが更新されたときにそれが上書きされたり削除されたりしないような方法で適切なテンプレートをテーマディレクトリにインストールすることです。これは、私が適切なテンプレートをpluginsディレクトリのfiel content-aside.php
に入れて、以下のように `` upgrader_process_complete 'にフックすることでできます
function install_aside_template_on_upgrade( $upgrader_object, $options ) {
if ($options['type'] == 'theme' ) {
$content_aside = plugin_dir_path( __FILE__ ) . 'content-aside.php';
$template_parts_content_aside = get_stylesheet_directory() . '/template-parts/content-aside.php';
copy($content_aside, $template_parts_content_aside);
}
}
add_action( 'upgrader_process_complete', 'install_aside_template_on_upgrade',10, 2);
このようにして、テーマが更新されるたびにcontent-aside.php
がテーマディレクトリにコピーされます。
これはかなりひどいハックであり、望ましくない副作用をもたらす可能性があることに注意してください。それでも、私はこれがいくつかのために役立つことができると思いました...
投稿された質問に対する正確な回答ではありませんが、このページに掲載される多くの人にとって実際に最適な解決策になると思われる、同様の何かを達成するためのさらにクリーンで簡単な方法があります。私には、この質問をしてから要件が少し変わったので、最終的にこの解決策に進むことができました。
カスタムテーマを使用する代わりに、多くの場合、テーマのテンプレートがthe_excerpt()
を呼び出したときにカスタム投稿タイプが返すものを変更するだけで十分です。これは、次のように'the_excerpt'
フィルタにフックすることで実現できます。
function paper_get_the_excerpt ($content) {
global $post;
$post_id = $post->ID;
if ( get_post_type($post_id) === 'paper' ) {
[do whatever you want with $content]
}
return $content;
}
add_filter( 'the_excerpt', 'paper_get_the_excerpt' );
きれいでシンプルで、テンプレートを変更するのと同じくらい柔軟性があります。