← Назад в «Блог»
2 368

Как сделать подстраницу для произвольного типа записей в wordpress

В этой статье расскажу, как без кучи кода сделать подстраницы у произвольного типа записей с сохранением структуры url.

Как делал раньше

Я пользовался костылём — разрывом страницы.

Как сделать подстраницу для произвольного типа записей в wordpress 1
Так выглядит разрыв страницы

Недостатки такого решения:

  • Url будут нечитабельными. Каждый разрыв страницы в url будет идти цифрой: /1, /2, /3. А я хочу, чтобы это были нормальные url: /logo, /process, /mobile
  • Всё в одной странице. Если вы создадите таких 5−6 разрывов с кучей контента, ваша админка начнёт загибаться.
  • Если же вы начнёте создавать страницы отдельно и связывать их допустим ACF — в списке страниц они могут быть далеко друг от друга.

Задача

У меня появилась задача делать подстраницы для моих кейсов на сайте. Чтобы можно было создать страницу под разный аспект проекта: дизайн сайта, дизайн приложения, логотип. Но чтобы всё было привязано к одному проекту и пользователь мог переключаться.

Выглядеть должно примерно так:

Как сделать подстраницу для произвольного типа записей в wordpress 2

Сделать так, чтобы можно было делать подстраницы, в решении этого мне нужно:

  • нормальные url, которыми я могу управлять
  • разделить страницы на разные, чтобы избежать нагрузки на админку
  • чтобы подстраницы были связаны с родительскими страницами в списке

Решение

Наше решение состоит из нескольких шагов

  1. Поменять параметры в создании произвольного типа записи
  2. Обновить постоянные ссылки
  3. Выбрать родительскую страницу у нескольких страниц
  4. Вывести подстраницы на родительской страницы
  5. Вывести подстраницы на каждой подстранице

Поменять параметры в создании произвольного типа записи

Вот так выглядит мой код создания произвольного типа записи.

    register_post_type('projects', array(
        'label'  => null,
        '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'          => 'Проекты', // название меню
        ),
        'description'         => '',
        'public'              => true,
        'publicly_queryable'  => true, // зависит от public
        'exclude_from_search' => false, // зависит от public
        'show_ui'             => true, // зависит от public
        'show_in_menu'        => true, // показывать ли в меню адмнки
        'show_in_admin_bar'   => true, // по умолчанию значение show_in_menu
        'show_in_nav_menus'   => true, // зависит от public
        'show_in_rest'        => true, // добавить в REST API. C WP 4.7
        'rest_base'           => null, // $post_type. C WP 4.7
        'menu_position'       => 4,
        'menu_icon'           => 'dashicons-format-gallery',
        'capability_type'   => 'page',
        //'capabilities'      => 'post', // массив дополнительных прав для этого типа записи
        //'map_meta_cap'      => null, // Ставим true чтобы включить дефолтный обработчик специальных прав
        'hierarchical'        => true,
        'supports'            => array('title', 'thumbnail','comments', 'editor', 'page-attributes','post-formats', 'excerpt', 'revisions', 'custom-fields'),
        'has_archive'         => false,
        'taxonomies'          => array('projectcategory'),
        'rewrite'             => true,
        'query_var'           => true
    ) );

Для нас важны параметры:

  • parent_item_colon
  • show_in_rest
  • rewrite
  • capability_type
  • hierarchical

Если у вас таких нет, скопируйте их из моего кода.

Что менять в коде:

  • parent_item_colon — он должен быть либо закомментирован, либо там должно быть что-то написано. Если будет просто пустое — он не покажет блок выбора родительской страницы
  • show_in_rest => true
  • rewrite => true
  • capability_type => true
  • hierarchical => true

Обновить постоянные ссылки

В админке переходим в: «Настройки → Постоянные ссылки». И нажать кнопку «Сохранить изменения».

Как сделать подстраницу для произвольного типа записей в wordpress 3

Выбрать родительскую страницу у нескольких страниц

Я создал тестовый проект и несколько подстраниц. У подстраниц выбрал родительскую страницу.

Как сделать подстраницу для произвольного типа записей в wordpress 4
Как сделать подстраницу для произвольного типа записей в wordpress 5

Вывести подстраницы на родительской странице

Теперь нам надо вывести их на родительской странице.

Будем использовать функцию get_childen, подробнее о ней можно почитать на WP Kama.

Иду в код single-project.php, у вас может быть свой шаблон детальной страницы.

Как сделать подстраницу для произвольного типа записей в wordpress 6

У меня уже тут стоит костыль от прошлого решения. Его мы и перепишем.

Вот такой код я скопировал с WP Kama, надо в post_parent поставить айди поста и вывести ссылки в цикле.

$childrens = get_children( [
	'post_parent' => 0, // попеняем на $post->ID
	'post_type'   => 'any',
	'numberposts' => -1,
	'post_status' => 'any'
] );

if( $childrens ){
	foreach( $childrens as $children ){
		// вывыдем ссылки
	}
}

Вот, что у меня получилось, пришлось попотеть, чтобы учесть всё. Не забудьте заменить projects на свою таксономи.

<?
  $parents = get_post_ancestors($post->ID); // выводим родителей страницы
  $parentPost = get_post($parents[0]); // выводим пост в отдельную странцу

  $childrens = get_children(  [
    'post_parent' => (!empty($parents)? $parents[0] : $post->ID), // если массив родителей не пустой — 
    'post_type'   => 'projects', // здесь вставьте свою таксономию
    'numberposts' => -1,
    'post_status' => 'any'
  ] );
?>


<!-- Выводим заголовок родительского поста, если он есть -->
<h1 class="case-title">
  <?if(!empty($parents)):?>
    <? echo $parentPost->post_title;?> <!-- Заголовок родителя -->
  <?else:?>
    <?the_title();?> <!-- Заголовок поста -->
  <?endif;?>
</h1>

<!-- Если нет родителей и детей, не выодим блок с ссылками -->
<?if (!empty($chilrens) & !empty($parents)):?>

  <!-- Контейнер с ссылками подстраниц -->
  <div>
    <!-- Выводим ссылку описание: 
            если у проекта есть родитель — выводим его ссылку.
            если у проекта есть дети — выводим его собственную ссылку -->
    <?if (!empty($parents)):?>
      <a href="<?=get_permalink($parents[0]);?>" class="project-page-tab js-tab-description">Описание</a> 
    <?elseif (!empty($childrens)):?>
      <a href="<?=get_permalink($post->ID);?>" class="project-page-tab js-tab-description">Описание</a> 
    <?endif;?>

    <!-- Выводим ссылки подстраниц, если есть -->
    <?if( $childrens ): ?>
      <? foreach( $childrens as $children ): ?>
        <!-- Выводим ссылку -->
          <a href="<?=get_permalink($children->ID);?>"><?=$children->post_title;?></a> 
      <?endforeach;
    endif;?>
  </div><!-- end контейнер с ссылками --> 

<?endif;?>

Что получилось в итоге

Обратите внимание на url.

Решение подсказал Дмитрий Воробьев.

Полезно
2
1
Непонятно
3
Поделиться
Отправить
Линкануть
Вотсапнуть

Канал о фрилансе

Там я делюсь фишками о фрилансе: деньги, клиенты, автоматизация, фриланс. Раньше это был закрытый материал с платным доступом. Сейчас он открыт. Иногда подписчикам будет открываться платные материалы.

Подписаться
← Назад в «Блог»

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *