Очень часто встречаю дизайны сайтов в которых внешний вид, к примеру, рубрики “Новости IT” и “Новости образования” отличаются. В CSM WordPress можно создавать отдельные шаблоны для рубрик, но для этого нужно править файлы темы. Создать один нестандартный шаблон для нескольких категорий одновременно не получится, т.к. имена файлов должны соответствовать идентификатору или ярлыку, а они уникальны.

Динамическое изменение шаблона в виде выпадающего списка доступно в консоли только для постов и страниц. Хотелось бы чтобы в консоли при создании и редактировании рубрики можно было быстро выбрать нужный шаблон и использовать его для разных рубрик одновременно. В этой статье будет рассмотрен пример добавление такого функционала для стандартных рубрик WordPress.

Реализация

Имя файла шаблона страницы или поста хранится в метаполе _wp_page_template таблицы БД wp_postmeta. При выборе шаблона WordPress получает значение этого поля и подключает нужный файл. Подробней про шаблоны страниц WordPress можно прочитать здесь: 3 способа создать шаблон страницы.

Для категорий используем подобный алгоритм работы, это:

  1. Получить список шаблонов в файлах темы
  2. Добавить поле с выбором шаблона на странице создания и редактирования рубрики
  3. Сохранить поле с выбранным шаблоном в метаданные рубрики
  4. В публичной части сайта подменить шаблон по умолчанию на нестандартный

Список шаблонов

В WordPress есть список подходящих названий файлов, каждое из названий проверяется по очереди на физическое существование такого файла. Как только WordPress видит что файл существует – поиск подходящего прекращается и найденный файл используется в качестве шаблона. Иерархия шаблонов и порядок их выбора для рубрик wordpress такой:

  1. category-{ярлык}.php
  2. category-{id}.php
  3. category.php
  4. archive.php
  5. paged.php (если страница пагинации)
  6. index.php

Подробней про иерархию шаблонов: Иерархия файлов темы (шаблона)

Список файлов шаблонов рубрик можно вписать в код в виде переменной при создании темы, а можно получить динамически. Мне больше нравится второй вариант. Для этого создадим отдельную функцию, которую подключим к пользовательскому фильтру category_custom_templates, это позволит получать список имён файлов и при необходимости изменять его в других частях темы.

Для получения списка файлов можно использовать php функцию glob (подробнее https://www.php.net/manual/ru/function.glob.php), аргументом функции будет путь к директории темы и шаблон имени файла для поиска.

Путь к директории темы получим с помощью функции get_stylesheet_directory().

Имя файла сформируем по аналогии первых двух из списка выше, т.е. такого формата category-{*}.php, где * – название шаблона. Это позволит добавить динамический выбор в консоли и сохранить стандартный функционал WordPress при котором шаблон выбирается с помощью ярлыка и идентификатора рубрики.

<?php

/**
 * Получение списока шаблонов
 * */
function get_category_templates( $templates ) {
  $theme_path = get_stylesheet_directory();
  $templates = array_merge( $templates, array_map( 'basename', glob( $theme_path . '/category-*.php', GLOB_BRACE ) ) );
  return $templates;
}

add_filter( 'category_custom_templates', 'get_category_templates', 10, 1 );

Добавление поля

Для добавления произвольных полей в админке рубрик предусмотрено два хука. Первый выводи html-вёрстку в форме создания категории и второй в форме редактирования:

  • category_add_form_fields – хук для вывода дополнительных полей в форму редактирования категории;
  • category_edit_form_fields – хук для вывода дополнительных полей в форму редактирования категории.

category – идентификатор таксономии, который можно заменить, к примеру, на product_cat для WooCommerce.

Вёрстка двух форм отличается, поэтому нужно создать две разные функции.

<?php

/**
 * Добавление поля для выбора шаблона в форме РЕДАКТИРОВАНИЯ категории
 */
function edit_category_custom_template( $term ) {

  // получаем идентификатор уже прикреплённого шаблона
  $custom_template = get_term_meta( $term->term_id, '_custom_template', true );

  // получаем список созданных шаблонов
  $templates = apply_filters( 'category_custom_templates', [] );

  // формируем html-код поля выбора сайдбара

  if ( is_array( $templates ) && ! empty( $templates ) ) : ?>
    <tr class="form-field">
      <th scope="row" valign="top">
        <label for="custom_template"><?php _e( 'Шаблон', THEME_TEXTDOMAIN ); ?></label>
      </th>
      <td>
        <select class="resume-control" id="custom_template" name="custom_template">
          <option value=""><?php _e( 'Стандартный шаблон', THEME_TEXTDOMAIN ); ?></option>
          <?php foreach ( $templates as $value ) : ?>
            <option value="<?php echo $value; ?>" <?php selected( $custom_template, $value, true ); ?> ><?php echo $value; ?></option>
          <?php endforeach; ?>
        </select>
      </td>
    </tr>
  <?php endif;
}

add_action( 'category_edit_form_fields', 'edit_category_custom_template' );


<?php

/**
 * Добавление поля для выбора шаблона в форме СОЗДАНИЯ категории
 */
function add_category_custom_template( $taxonomy_slug ) {

  // получаем список созданных шаблонов
  $templates = apply_filters( 'category_custom_templates', [] );

  // формируем html-код поля выбора сайдбар
  if ( is_array( $templates ) && ! empty( $templates ) ) : ?>
    <div class="form-field">
      <label for="custom_template"><?php _e( 'Шаблон', THEME_TEXTDOMAIN ); ?></label>
      <select class="resume-control" id="custom_template" name="custom_template">
        <option value=""><?php _e( 'Стандартный шаблон', THEME_TEXTDOMAIN ); ?></option>
        <?php foreach ( $templates as $value ) : ?>
          <option value="<?php echo $value; ?>" ><?php echo $value; ?></option>
        <?php endforeach; ?>
      </select>
    </div>
  <?php endif;
}

add_action( 'category_add_form_fields', 'add_category_custom_template' );

Сохранение шаблона

Сохранение данных категории при создании и редактировании происходит во время работы разных хуков, это

  • create_category
  • edited_category

Алгоритм работы у них одинаковый. Можно создать одну функцию и подключить её к обоим хукам. Функция будет делать следующее:

  1. проверит имеет ли текущий пользователь права на редактирование категории
  2. проверит nonce-поле безопасности
  3. провалидирует (очистит) идентификатор шаблона из глобального массива $_POST
  4. сохранит или удалит идентификатор шаблона из метаданных категории
<?php

/**
 * Функция сохранения идентификатора прикреплённого шаблона в метаполе категории
 */
function save_category_custom_template( $term_id ) {
  if ( ! current_user_can( 'edit_term', $term_id ) ) return;
  if (
    ( isset( $_POST[ '_wpnonce' ] ) && ! wp_verify_nonce( $_POST[ '_wpnonce' ], "update-tag_$term_id" ) ) ||
    ( isset( $_POST[ '_wpnonce_add-tag' ] ) && ! wp_verify_nonce( $_POST[ '_wpnonce_add-tag' ], "add-tag" ) )
  ) return;
  $custom_template = ( isset( $_POST[ 'custom_template' ] ) ) ? sanitize_text_field( wp_unslash( $_POST[ 'custom_template' ] ) ) : '';
  if ( empty( $custom_template ) ) {
    delete_term_meta( $term_id, '_custom_template' );
  } else {
    update_term_meta( $term_id, '_custom_template', $custom_template );
  }
  return $term_id;
}

add_action( 'create_category', 'save_category_custom_template' );
add_action( 'edited_category', 'save_category_custom_template' );

Замена шаблона

Для динамического изменения шаблона используется хук template_include. Фильтр срабатывает после события template_redirect и после того, как WordPress подберёт файл, который будет использоваться в качестве шаблона.

/**
 * Выбор шаблона в публичной части сайта
 * */
function category_custom_template_include( $default_template ) {
  if ( is_category() ) {
    $category = get_queried_object();
    $custom_template = get_term_meta( $category->term_id, '_custom_template', true );
    $templates = apply_filters( 'category_custom_templates', [] );
    if ( ! empty( $custom_template ) && in_array( $custom_template, $templates ) ) {
      $default_template = get_stylesheet_directory() . '/' . $custom_template;
    }
  }
  return $default_template;
}

add_filter( 'template_include', 'category_custom_template_include' );

Итог

Был рассмотрен пример добавления динамического списка выбора шаблона для категорий.

Ссылка на git с полным кодом: category-templates.php

Код необходимо подключить в файле functions.php темы. Код можно модифицировать и использовать стандартных Рубрик WordPress и для пользовательских таксономий.

52голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x
()
x