Назначение Шаблона Страницы В Пользовательском Типе Записи
Я зарегистрировал пользовательский тип записи и создал файл с именем archive-myCPT.php и еще один для отдельных сообщений под названием single-myCPT.php.
Что я хочу сделать, так это создать страницу, на которой я покажу всего несколько сообщений из моего пользовательского типа сообщений. Внутри моего archive-myCPT.php У меня будет ссылка под названием, скажем, "Специальные сообщения", и эта ссылка перейдет на пользовательскую страницу, которая будет немного отличаться от archive-myCPT.php , единственная разница заключается в том, что здесь я буду использовать пользовательский запрос для сообщений.
Единственный способ сделать это, по-видимому, создать шаблон страницы, но проблема здесь в том, что я не могу назначить шаблон страницы страницам в моем CPT. Я нашел этот плагин , который может помочь мне с поддержкой шаблонов страниц для моего пользовательского типа сообщений, но он довольно старый, и я не знаю, совместим ли он с последней версией WordPress.
Есть ли какой-либо другой способ добиться этого?
Является ли это обычная/эффективная практика?
Может быть, вы могли бы порекомендовать что-нибудь еще?
2 answers
Если вы добавляете пользовательский запрос в шаблон для загрузки записей, тип записи на этой странице не обязательно должен быть вашим пользовательским типом записи. Вы можете создать обычный ванильный page
, создать шаблон для этого с помощью page-your_page_slug.php
или с помощью пользовательского шаблона, назначенного в раскрывающемся списке шаблоны, а затем запросить любой тип записи, который вы хотите, с помощью WP_Query
.
РЕДАКТИРОВАТЬ - вот пример использования фильтра single_template
. вам придется изменить тип сообщения и слаг, чтобы они соответствовали вашим.
function wpa_single_cpt_template( $templates = '' ){
$single = get_queried_object();
if( 'myCPT' == $single->post_type
&& 'my-special-slug' == $single->post_name )
$templates = locate_template( 'my-special-template.php', false );
return $templates;
}
add_filter( 'single_template', 'wpa_single_cpt_template' );
Адаптировано из пример иерархии шаблонов : Иерархия фильтров.
Вы могли бы подумать, что это будет так же просто, как добавить add_post_type_support( 'cptslug', 'page-attributes' );
в ваш код, но это не так. Если вы проверите источник, вы увидите, что раскрывающийся список шаблонов ограничен только типом записи page
. Существует также примечание в Кодексе и ссылка на закрытый билет на маршрут по этой теме.
Вы можете добавить это поле в свой CPT, скопировав основную функцию, сделав небольшое редактирование и добавив новое поле.
function my_cpt_attributes_meta_box($post) {
$post_type_object = get_post_type_object($post->post_type);
if ( $post_type_object->hierarchical ) {
$dropdown_args = array(
'post_type' => $post->post_type,
'exclude_tree' => $post->ID,
'selected' => $post->post_parent,
'name' => 'parent_id',
'show_option_none' => __('(no parent)'),
'sort_column' => 'menu_order, post_title',
'echo' => 0,
);
$dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post );
$pages = wp_dropdown_pages( $dropdown_args );
if ( ! empty($pages) ) {
?>
<p><strong><?php _e('Parent') ?></strong></p>
<label class="screen-reader-text" for="parent_id"><?php _e('Parent') ?></label>
<?php echo $pages; ?>
<?php
} // end empty pages check
} // end hierarchical check.
$template = get_post_meta($post->ID,'_wp_page_template',true);
?>
<p><strong><?php _e('Template') ?></strong></p>
<label class="screen-reader-text" for="page_template"><?php _e('Page Template') ?></label><select name="page_template" id="page_template">
<option value='default'><?php _e('Default Template'); ?></option>
<?php page_template_dropdown($template); ?>
</select>
<p><strong><?php _e('Order') ?></strong></p>
<p><label class="screen-reader-text" for="menu_order"><?php _e('Order') ?></label><input name="menu_order" type="text" size="4" id="menu_order" value="<?php echo esc_attr($post->menu_order) ?>" /></p>
<p><?php if ( 'page' == $post->post_type ) _e( 'Need help? Use the Help tab in the upper right of your screen.' ); ?></p>
<?php
}
function add_my_cpt_attributes_meta_box() {
add_meta_box(
'my_cpt_attributes_meta_box',
'My Box Name',
'my_cpt_attributes_meta_box',
'book',
'side',
'core'
);
}
add_action( 'add_meta_boxes', 'add_my_cpt_attributes_meta_box' );
Если вы протестируете этот код, вы будете обратите внимание, что поле появляется, но данные не сохраняются. Вот почему.
Нам придется самим сохранять данные.
function my_save_cpt_template($post_ID,$post) {
$page_template = (isset($_POST['page_template'])) ? $_POST['page_template'] : false;
$page_templates = wp_get_theme()->get_page_templates();
// var_dump($page_template,$page_templates,'default' != $page_template && ! isset( $page_templates[ $page_template ] )); die;
if ( 'default' != $page_template && ! isset( $page_templates[ $page_template ] ) ) {
if ( $wp_error )
return new WP_Error('invalid_page_template', __('The page template is invalid.'));
else
return 0;
}
update_post_meta($post_ID, '_wp_page_template', $page_template);
}
add_action('save_post_cptslug','my_save_cpt_template',1,2);
Теперь он должен сохраниться, но шаблон не загружается. Вот почему. get_single_template
выполняется перед get_page_template
, и get_page_template
- это то, что ищет специализированные шаблоны. Поэтому нам нужно загрузить этот шаблон самим.
add_action(
'template_include',
function ($template) {
global $post;
if (is_singular() && isset($post->post_type) && 'book' === $post->post_type) {
$new = get_post_meta($post->ID,'_wp_page_template',true);
$new = locate_template($new);
if (!empty($new)) {
$template = $new;
}
}
return $template;
}
);
Едва проверено. Возможно, глючит. Будьте бдительны. Никаких возвратов.