問題描述
我有一個自定義的帖子型別 paper 定義在我的 wordpress 外掛,我顯示,連同標準的帖子,主要查詢透過:
function add_custom_post_types_to_query( $query ) {
if ( is_home() && $query->is_main_query() )
$query->set( 'post_type', array( 'post', 'paper' ) );
// return $query; //As was pointed out by Ihor Vorotnov this is not necessary.
}
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'使用的各種程式碼,但是無濟於事。
最佳解決方案
Background
不幸的是,get_template_part()功能沒有任何合適的過濾器來實現你想要的。可以使用 get_template_part_{$slug}動作鉤來注入模板部分,但是,對主題或子主題沒有任何改變,原始的模板部分將被新增。因此,您將無法替換現有的模板部件。
但是,您可以透過以下選項之一獲得所需的結果:
選項 1:使用預設的 CSS 類:
如果只需要更改 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 */
}
選項 2:修改 CSS 類:
如果預設的 CSS 類不足夠,您還可以使用外掛中的 post_class 過濾器鉤子來修改 (新增/刪除)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 條目的樣式。
選項 3:修改模板& 模板部分
如果您只想定位 CSS 類,您的所需樣式更改是不可能的,那麼您也可以從外掛中更改模板部分。但是,由於透過使用鉤子替換由 get_template_part()新增的模板部件是不可能的,因此您必須以某種方式更改模板,以便您可以從外掛中修改 get_template_part()呼叫。
為此,您可以定位 pre_get_posts 鉤子功能,並使用 template_include 濾鏡鉤來修改主頁模板,如下所示:
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' );
然後使用以下 CODE(根據需要進行修改):
// 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或主題用於主頁模板的任何主題) 複製主頁模板的 CODE 。 -
現在在
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目錄將表現為模板部件的子主題 – 即簡單的 drop-in 替換。
參考文獻
注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。