Отображение одного типа записей на двух разных шаблонах single

11 дек. 2017 г., 18:33:30
Просмотры: 1.32K
Голосов: 1

У меня есть клиент, который хочет отображать планы домов (custom post type) на своем сайте в двух разных разделах с разным оформлением, в зависимости от того, с какой страницы списка был осуществлен переход к записи. Я нашел это решение от @gmazzap нескольких летней давности, и оно выглядит перспективным, но у меня не получается заставить его работать: Несколько шаблонов для custom post type

Конкретно, не удается модифицировать URL на альтернативной странице списка: он просто использует slug, указанный при регистрации CPT:

'rewrite' => array( 'slug' => 'plan', 'with_front' => false ),

Это означает, что когда я кликаю на ссылку плана в шаблоне 'page_kioskoverview.php', запись отображается на стандартном шаблоне 'single-plans.php', а не на альтернативном 'single-kioskplans.php'.

Вот как выглядит мой код:

add_action('template_redirect', 'change_plans_plink');
function change_plans_plink() {
  if (is_page_template('page_kioskoverview.php')) { 
    add_filter( 'post_link', 'plans_query_string', 10, 2 );
  }
}
function plans_query_string( $url, $post ) {
  if ( $post->post_type === 'plans' ) { 
    $url = add_query_arg( array('style'=>'alt'), $url );
  }
  return $url;
}

// Назначаем альтернативный single-шаблон для ссылки с параметром alt
add_action('template_include', 'kiosk_plan_single');
function kiosk_plan_single($template) {
  if( is_singular('plans') ) {
    $alt = filter_input(INPUT_GET, 'style', FILTER_SANITIZE_STRING);
    if ( $alt === 'alt' ) $template = 'single-kioskplans.php';
  }
  return $template;
}

После нескольких дней изучения (и попыток различных вариаций без успеха), я не могу обнаружить проблему, но должно быть что-то упускаю.

0
Все ответы на вопрос 3
1

Для отображения разных шаблонов для одного типа записи я бы создал 2 разные ссылки, проверял, на какой ссылке я нахожусь, и выбирал, какой шаблон загружать.

Рабочий пример:

/**
 * Регистрация типа записи "Событие"
 *
 * Регистрация типа записи "Событие" добавит такую структуру постоянных ссылок: event/([^/]+)/?$
 */
function wpse_288345_register_event_post_type() {

    $labels = array(
        'name' => __( 'События' ),
        'singular_name' => __( 'Событие' ),
        'add_new' => __( 'Добавить новое' ),
        'add_new_item' => __( 'Добавить новое' ),
        'edit_item' => __( 'Редактировать' ),
        'new_item' => __( 'Новое' ),
        'view_item' => __( 'Просмотреть' ),
        'search_items' => __( 'Поиск' ),
        'not_found' => __( 'Не найдено' ),
        'not_found_in_trash' => __( 'События не найдены в корзине' ),
        'parent_item_colon' => __( 'Родительский' ),
        'menu_name' => __( 'События' ),

    );

    $args = array(
        'labels' => $labels,
        'hierarchical' => false,
        'supports' => array( 'title', 'page-attributes' ),
        'taxonomies' => array(),
        'public' => true,
        'show_ui' => true,
        'show_in_menu' => true,
        'show_in_nav_menus' => false,
        'publicly_queryable' => true,
        'exclude_from_search' => false,
        'has_archive' => true,
        'query_var' => true,
        'can_export' => true,
        'rewrite' => array('slug' => 'event'),
        'capability_type' => 'post',
    );

    register_post_type( 'event', $args );
}

add_action( 'init', 'wpse_288345_register_event_post_type' );

/**
 * Добавление пользовательских правил перезаписи для типа записи "Событие".
 *
 * Не забудьте сбросить правила перезаписи для применения изменений.
 */
function wpse_288345_add_event_rewrite_rules() {

    /**
     * Пользовательские правила перезаписи для одного типа записи.
     * 
     * Мы будем знать, на каком URL находимся, по параметрам $_GET 'performers' и 'summary', которые мы добавим в
     * публичные переменные запроса для удобного доступа.
     */
    add_rewrite_rule('event/performers/([^/]+)/?$', 'index.php?post_type=event&name=$matches[1]&performers=1', 'top');
    add_rewrite_rule('event/summary/([^/]+)/?$', 'index.php?post_type=event&name=$matches[1]&summary=1', 'top');
}

add_action('init', 'wpse_288345_add_event_rewrite_rules');

/**
 * Добавление пользовательских переменных запроса 'performers' и 'summary' для событий.
 */
function wpse_288345_register_event_query_vars( $vars ) {

    $vars[] = 'performers';
    $vars[] = 'summary';

    return $vars;
}

add_filter( 'query_vars', 'wpse_288345_register_event_query_vars' );

/**
 * Определение, какой шаблон загружать
 */
function wpse_288345_load_performers_or_summary_template( $template ) {

    // Получение публичных переменных запроса
    $performers = (int) get_query_var( 'performers', 0 );
    $summary    = (int) get_query_var( 'summary', 0 );

    // Если performer = 1, значит мы на ссылке event/performers
    if( $performers === 1 ) {
        $template = locate_template( array( 'single-event-performers.php' ) );
    }

    // Если summary = 1, значит мы на ссылке event/summary
    if( $summary === 1 ) {
        $template = locate_template( array( 'single-event-summary.php' ) );
    }

    if($template == '') {
        throw new \Exception('Шаблон не найден');
    }

    return $template;
}

add_filter( 'template_include', 'wpse_288345_load_performers_or_summary_template' );
12 дек. 2017 г. 09:58:43
Комментарии

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

Ray Gulick Ray Gulick
12 дек. 2017 г. 15:11:12
0

Вот альтернативный подход, который у меня сработал, с использованием GET-параметра и условных операторов.

  1. На странице альтернативного списка я добавил '?template=kiosk' к постоянным ссылкам.

  2. В шаблоне для одиночных записей (single-plans.php) я добавил следующее в начале шаблона (и, конечно, 'endif' в конце шаблона):

    $kiosk = $_GET['template'];
    if(isset($kiosk)) :
  3. Затем, в шаблоне я создал условные операторы в зависимости от наличия параметра, чтобы отображать контент соответствующим образом:

    if(isset($kiosk)) { 
        // показать версию для киоска
        } else {
        // показать стандартную версию
        }

12 дек. 2017 г. 15:32:39
0

Я тоже пробовал почти такой же код, и он не работал. Нужно внести всего одно изменение, чтобы всё заработало. Просто добавьте locate_template в одну строку.

Замените

if ( $alt === 'alt' ) $template = 'single-kioskplans.php';

на

if ( $alt === 'alt' ) $template = locate_template('single-kioskplans.php');

Полный код будет выглядеть так:

add_action('template_redirect', 'change_plans_plink');
function change_plans_plink() {
  if (is_page_template('page_kioskoverview.php')) { 
    add_filter( 'post_link', 'plans_query_string', 10, 2 );
  }
}
function plans_query_string( $url, $post ) {
  if ( $post->post_type === 'plans' ) { 
    $url = add_query_arg( array('style'=>'alt'), $url );
  }
  return $url;
}

//назначение альтернативного шаблона single для ссылки с alt
add_action('template_include', 'kiosk_plan_single');
function kiosk_plan_single($template) {
  if( is_singular('plans') ) {
    $alt = filter_input(INPUT_GET, 'style', FILTER_SANITIZE_STRING);
    if ( $alt === 'alt' ) $template = locate_template('single-kioskplans.php');
  }
  return $template;
}
30 окт. 2020 г. 21:03:35