Проблема с использованием Custom Post Type в качестве главной страницы

12 апр. 2012 г., 01:24:01
Просмотры: 885
Голосов: 1

Я написал плагин, который использует 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 в качестве главной страницы. Но... у меня есть несколько проблем:

  1. Если выбрать стандартную настройку "Последние записи" — ВСЁ РАБОТАЕТ
  2. Если выбрать страницу Custom Post Type в качестве главной — ВСЁ РАБОТАЕТ

Проблема возникает, когда вы выбираете обычную СТРАНИЦУ в качестве главной. Она наследует шаблон Custom Post Type и, естественно, не показывает контент страницы, потому что для него нет кода.

Я уверен, что решение простое, но не знаю, что нужно изменить.

Есть идеи? Буду очень благодарен за помощь.

2
Комментарии

В настройках вашего CPT вы, вероятно, видите что-то подобное: 'rewrite' => array( 'with_front' => true, 'pages' => true, 'feeds' => true, 'slug' => 'post_type', ), Если вы попробуете изменить 'with_front' на false и также изменить 'slug', сохраняются ли те же проблемы?

David David
12 апр. 2012 г. 01:39:17

Дэвид, да, я получаю тот же результат. Хотя я не совсем понял, что вы имели в виду под изменением 'slug'

Armand Armand
12 апр. 2012 г. 02:31:03
Все ответы на вопрос 1
7

Ошибка в добавленном вами коде:

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/.

12 апр. 2012 г. 02:15:04
Комментарии

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

Armand Armand
12 апр. 2012 г. 02:30:08

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

EAMann EAMann
12 апр. 2012 г. 02:41:26

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

Armand Armand
12 апр. 2012 г. 14:17:56

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

EAMann EAMann
12 апр. 2012 г. 16:35:27

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

Armand Armand
12 апр. 2012 г. 16:42:41

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

EAMann EAMann
12 апр. 2012 г. 18:28:50

EAMann. Я очень благодарен за вашу помощь. Я попробую это и сообщу всем о результатах. Еще раз спасибо.

Armand Armand
13 апр. 2012 г. 13:10:51
Показать остальные 2 комментариев