Проблема с использованием Custom Post Type в качестве главной страницы
Я написал плагин, который использует Custom Post Types для создания серии страниц. У меня есть код, который добавляет CPT в выпадающее меню "Настройки чтения", и он отлично работает.
Вот этот код...
add_filter( 'get_pages', 'add_wpwebinar_front' );
function add_wppwebinar_front( $pages ) {
// Запрос для получения страниц типа wpwebinar
$my_wpwebinar_pages = new WP_Query( array( 'post_type' => 'wpwebinar' ) );
if ( $my_wpwebinar_pages->post_count > 0 ) {
// Объединяем обычные страницы с CPT
$pages = array_merge( $pages, $my_wpwebinar_pages->posts );
}
return $pages;
}
Код работает, но если выбрать Custom Post Type в качестве главной страницы, происходит редирект на фактическую страницу CPT. Например, domain.com перенаправляет на domain.com/slug/названиестраницы
Чтобы это исправить, я добавил этот код...
function enable_front_page_stacks( $query ){
global $post, $wp_query;
// Если тип записи не указан и установлен ID страницы
if('' == $query->query_vars['post_type'] && 0 != $query->query_vars['page_id'])
// Устанавливаем тип записи как wpwebinar
$query->set('post_type', 'wpwebinar');
}
add_action( 'pre_get_posts', 'enable_front_page_stacks' );
Это сохраняет Custom Post Type в качестве главной страницы. Но... у меня есть несколько проблем:
- Если выбрать стандартную настройку "Последние записи" — ВСЁ РАБОТАЕТ
- Если выбрать страницу Custom Post Type в качестве главной — ВСЁ РАБОТАЕТ
Проблема возникает, когда вы выбираете обычную СТРАНИЦУ в качестве главной. Она наследует шаблон Custom Post Type и, естественно, не показывает контент страницы, потому что для него нет кода.
Я уверен, что решение простое, но не знаю, что нужно изменить.
Есть идеи? Буду очень благодарен за помощь.

Ошибка в добавленном вами коде:
function enable_front_page_stacks( $query ){
global $post, $wp_query;
if('' == $query->query_vars['post_type'] && 0 != $query->query_vars['page_id'])
$query->set('post_type', 'wpwebinar');
}
Конкретно проблема в $query->set()
. Этот вызов принудительно устанавливает тип записи "wpwebinar", если он явно не задан. В результате, при загрузке обычной страницы система будет считать её типом "wpwebinar" и использовать шаблон для пользовательского типа записи.
Вместо этого измените функцию следующим образом:
function enable_front_page_stacks( $query ){
if(( ! isset($query->query_vars['post_type']) || '' == $query->query_vars['post_type']) && 0 != $query->query_vars['page_id'])
$query->query_vars['post_type'] = array( 'page', 'wpwebinar' );
}
Это оригинальная функция enable_front_page_stacks()
, но с использованием "wpwebinar" вместо "stack" в качестве дополнительного пользовательского типа записи.
Подключение файла шаблона из плагина
Обычно лучшей практикой считается регистрация CPT (пользовательского типа записи) через плагин, а шаблоны для CPT оставлять на усмотрение темы. Такой подход лучше согласуется со стилями и даёт конечному пользователю полный контроль над дизайном сайта. Однако в редких случаях имеет смысл указывать шаблон CPT непосредственно в самом плагине.
Для реализации этого нужно подключиться к функции get_single_template()
в ядре WordPress, чтобы указать, откуда брать файл. Вот стандартный порядок запроса:
template-loader.php
--> if ( is_single() ) $template = get_single_template()
-- --> template.php -> get_single_template()
-- -- --> $templates[] = array( 'single.php', 'single-{post_type}.php' );
-- -- --> return get_query_template( 'single', $templates )
-- -- -- --> template.php -> get_query_template( $type, $templates )
-- -- -- -- --> if ( empty($templates) ) $templates = array( '{$type}.php' );
-- -- -- -- --> return apply_filters( "{$type}_template", locate_template( $templates ) )
Чтобы зарегистрировать шаблон CPT из плагина, нужно подключиться к этому фильтру и указать расположение файла.
function load_plugin_cpt_template( $path ) {
$path = dirname(__FILE__) . '/single-wpwebinar.php';
return $path;
}
add_filter( 'wpwebinar_template', 'load_plugin_cpt_template' );
Я использую dirname( __FILE__ )
выше, предполагая, что ваш шаблон CPT находится на том же уровне, что и файл с этой функцией. Если это не так, скорректируйте путь. Обратите внимание, что эта функция полностью переопределит любой файл single-wpwebinar.php
, указанный в теме.
В качестве защиты можно проверить переданное значение $path
, чтобы убедиться, что используется single.php
или переопределение из темы, но это оставляю на ваше усмотрение.
Также на моём сайте есть более полное руководство: http://jumping-duck.com/tutorial/theme-ready-custom-post-types-in-wordpress/.

EAMann, я пробовал это, но проблема будет обратной - страница CPT теперь использует стандартный шаблон страницы, а НЕ шаблон CPT. В итоге получается страница, по сути, только с заголовком. Вот почему я использовал модифицированную версию вашего исходного кода с $query->set. Используя $query->set, страница использует шаблон CPT, но фактическая страница, установленная в "Настройках чтения", принимает шаблон CPT. Понимаете, о чем я?

Мне нужно увидеть, как выглядят ваши шаблоны, потому что ваш CPT должен использовать single-wpwebinar.php
в качестве шаблона, если вы используете тот же код.

Я использую 'template_redirect' для изменения расположения страницы single-wpwebinar.php. Возможно, это влияет на ситуацию. Проблема в том, что страница CPT не применяет созданный мной шаблон CPT. Я пробовал переместить single-wp-webinar.php в корень темы для теста и убрать template-redirect, но результат тот же. CPT по-прежнему наследует обычный шаблон страницы.

Если ваш CPT зарегистрирован как wpwebinar
, вы должны использовать шаблон single-wpwebinar.php
в теме. single-wp-webinar.php
не будет работать. И если вы переопределяете тему с помощью плагина, я бы сказал, что вы делаете что-то не так... но это уже более длинное обсуждение. Более простой путь здесь — создать ваш CPT, создать шаблонную страницу для CPT, а затем зарегистрировать шорткод, который можно использовать на стандартной странице для отображения вашего CPT.

single-wp-webinar.php была опечаткой. Я использую single-wpwebinar.php. Весь смысл в том, что CPT ЭТО ПЛАГИН. Поэтому single-wpwebinar.php находится в папке плагинов, и именно поэтому я использую template_redirect, чтобы получить правильное расположение шаблона.

Если вы абсолютно уверены, что ваш шаблонный файл должен находиться в плагине, а не в теме... смотрите мое обновление о том, как это сделать.
