Как правильно присвоить шаблон страницы для кастомного типа записи?

Ссылка скопирована
1 ответ

Салют всем!
Задача: присвоить шаблон страницы для кастомного типа записи
Ожидание: пост кастомного типа записи открывается по адресу "домен/страна/город/университет/каталог-курсов/курс", где "страна" и "город" это кастомные таксономии присвоенные для поста кастомного типа записи "университет", а "курс" это кастомного типа записи "курсы"
Вводные:
Регистрация кастомного типа записи "курсы":

register_post_type( 'courses', [ 		'label'  => null, 		'labels' => [ 			'name'               => 'Courses', // основное название для типа записи 			'singular_name'      => 'Course', // название для одной записи этого типа 			'add_new'            => 'Add Course', // для добавления новой записи 			'add_new_item'       => 'Add Course', // заголовка у вновь создаваемой записи в админ-панели. 			'edit_item'          => 'Edit Course', // для редактирования типа записи 			'new_item'           => 'New Course', // текст новой записи 			'view_item'          => 'View Course', // для просмотра записи этого типа. 			'search_items'       => 'Search Course', // для поиска по этим типам записи 			'not_found'          => 'Not found Course', // если в результате поиска ничего не было найдено 			'not_found_in_trash' => 'Not found Course in trash', // если не было найдено в корзине 			'parent_item_colon'  => '', // для родителей (у древовидных типов) 			'menu_name'          => 'Courses', // название меню 		], 		'description'            => 'Educate Online Courses', 		'public'                 => true, 		// 'publicly_queryable'  => null, // зависит от public 		// 'exclude_from_search' => null, // зависит от public 		// 'show_ui'             => null, // зависит от public 		'show_in_nav_menus'   => true, // зависит от public 		'show_in_menu'           => null, // показывать ли в меню админки 		// 'show_in_admin_bar'   => null, // зависит от show_in_menu 		'show_in_rest'        => null, // добавить в REST API. C WP 4.7 		'rest_base'           => null, // $post_type. C WP 4.7 		'menu_position'       => null, 		'menu_icon'           => 'dashicons-welcome-learn-more', 		//'capability_type'   => 'post', 		//'capabilities'      => 'post', // массив дополнительных прав для этого типа записи 		//'map_meta_cap'      => null, // Ставим true чтобы включить дефолтный обработчик специальных прав 		'hierarchical'        => true, 		'supports'            => [ 'title','editor','author','thumbnail','excerpt','trackbacks','custom-fields','comments','revisions','page-attributes','post-formats' ], // 'title','editor','author','thumbnail','excerpt','trackbacks','custom-fields','comments','revisions','page-attributes','post-formats' 		'taxonomies'          => true, 		'has_archive'         => 'courses', 		'rewrite' => array( 			'slug' => 'universities/%country%/%city%/%university%/courses', 			'with_front' => true, 			'feeds' => false, 			'pages' => true, 		), 		'query_var'           => true, 	] );

register_post_type( 'courses', [ 'label' => null, 'labels' => [ 'name' => 'Courses', // основное название для типа записи 'singular_name' => 'Course', // название для одной записи этого типа 'add_new' => 'Add Course', // для добавления новой записи 'add_new_item' => 'Add Course', // заголовка у вновь создаваемой записи в админ-панели. 'edit_item' => 'Edit Course', // для редактирования типа записи 'new_item' => 'New Course', // текст новой записи 'view_item' => 'View Course', // для просмотра записи этого типа. 'search_items' => 'Search Course', // для поиска по этим типам записи 'not_found' => 'Not found Course', // если в результате поиска ничего не было найдено 'not_found_in_trash' => 'Not found Course in trash', // если не было найдено в корзине 'parent_item_colon' => '', // для родителей (у древовидных типов) 'menu_name' => 'Courses', // название меню ], 'description' => 'Educate Online Courses', 'public' => true, // 'publicly_queryable' => null, // зависит от public // 'exclude_from_search' => null, // зависит от public // 'show_ui' => null, // зависит от public 'show_in_nav_menus' => true, // зависит от public 'show_in_menu' => null, // показывать ли в меню админки // 'show_in_admin_bar' => null, // зависит от show_in_menu 'show_in_rest' => null, // добавить в REST API. C WP 4.7 'rest_base' => null, // $post_type. C WP 4.7 'menu_position' => null, 'menu_icon' => 'dashicons-welcome-learn-more', //'capability_type' => 'post', //'capabilities' => 'post', // массив дополнительных прав для этого типа записи //'map_meta_cap' => null, // Ставим true чтобы включить дефолтный обработчик специальных прав 'hierarchical' => true, 'supports' => [ 'title','editor','author','thumbnail','excerpt','trackbacks','custom-fields','comments','revisions','page-attributes','post-formats' ], // 'title','editor','author','thumbnail','excerpt','trackbacks','custom-fields','comments','revisions','page-attributes','post-formats' 'taxonomies' => true, 'has_archive' => 'courses', 'rewrite' => array( 'slug' => 'universities/%country%/%city%/%university%/courses', 'with_front' => true, 'feeds' => false, 'pages' => true, ), 'query_var' => true, ] );

Важный момент: реврайт для слага 'slug' => 'universities/%country%/%city%/%university%/courses',
Так же, создал в проекте файл для кастомного типа записи single-courses.php.

Что я делал: добавил код для изменения структуры ссылок для типа записи Courses:

function custom_post_type_permalink($permalink, $post, $leavename) {     if ($post->post_type == 'universities') {         $countries = get_the_terms($post->ID, 'country');         $cities = get_the_terms($post->ID, 'city');          if ($countries && !is_wp_error($countries) && $cities && !is_wp_error($cities)) {             $country = $countries[0]->slug;             $city = $cities[0]->slug;              $permalink = str_replace('%country%', $country, $permalink);             $permalink = str_replace('%city%', $city, $permalink);         }     } elseif ($post->post_type == 'subjects') {         $schools = get_the_terms($post->ID, 'schools');         $disciplines = get_the_terms($post->ID, 'disciplines');          if ($schools && !is_wp_error($schools) && $disciplines && !is_wp_error($disciplines)) {             $school = $schools[0]->slug;             $discipline = $disciplines[0]->slug;              $permalink = str_replace('%schools%', $school, $permalink);             $permalink = str_replace('%disciplines%', $discipline, $permalink);         }     } elseif ($post->post_type == 'courses') {         $countries = wp_get_post_terms($post->ID, 'country');         $cities = wp_get_post_terms($post->ID, 'city');         $university = wp_get_post_terms($post->ID, 'universities');          if (!empty($countries) && !empty($cities) && !empty($university)) {             $country_slug = $countries[0]->slug;             $city_slug = $cities[0]->slug;             $university_slug = $university[0]->slug;              $permalink = str_replace('%country%', $country_slug, $permalink);             $permalink = str_replace('%city%', $city_slug, $permalink);             $permalink = str_replace('%university%', $university_slug, $permalink);         }     }      return $permalink; } add_filter('post_type_link', 'custom_post_type_permalink', 10, 3);  // Фильтр для изменения ссылок на таксономии function custom_taxonomy_permalink($termlink, $term, $taxonomy) {     if ($taxonomy == 'country' || $taxonomy == 'city') {         $country = null;         $city = null;          if ($taxonomy == 'country') {             $country = $term->slug;         } elseif ($taxonomy == 'city') {             $country_term = get_term($term->parent, 'country');             if ($country_term && !is_wp_error($country_term)) {                 $country = $country_term->slug;             }             $city = $term->slug;         }          if ($country) {             $termlink = str_replace('%country%', $country, $termlink);         }         if ($city) {             $termlink = str_replace('%city%', $city, $termlink);         }     } elseif ($taxonomy == 'schools' || $taxonomy == 'disciplines' || $taxonomy == 'universities') {         $school = null;         $discipline = null;          if ($taxonomy == 'schools') {             $school = $term->slug;         } elseif ($taxonomy == 'disciplines') {             $school_term = get_term($term->parent, 'schools');             if ($school_term && !is_wp_error($school_term)) {                 $school = $school_term->slug;             }             $discipline = $term->slug;         } elseif ($taxonomy == 'universities') {             // Для таксономии universities, необходимо сделать дополнительную замену             $termlink = str_replace('%university%', $term->slug, $termlink);         }          if ($school) {             $termlink = str_replace('%schools%', $school, $termlink);         }         if ($discipline) {             $termlink = str_replace('%disciplines%', $discipline, $termlink);         }     }     return $termlink; } add_filter('term_link', 'custom_taxonomy_permalink', 10, 3);

function custom_post_type_permalink($permalink, $post, $leavename) { if ($post->post_type == 'universities') { $countries = get_the_terms($post->ID, 'country'); $cities = get_the_terms($post->ID, 'city'); if ($countries && !is_wp_error($countries) && $cities && !is_wp_error($cities)) { $country = $countries[0]->slug; $city = $cities[0]->slug; $permalink = str_replace('%country%', $country, $permalink); $permalink = str_replace('%city%', $city, $permalink); } } elseif ($post->post_type == 'subjects') { $schools = get_the_terms($post->ID, 'schools'); $disciplines = get_the_terms($post->ID, 'disciplines'); if ($schools && !is_wp_error($schools) && $disciplines && !is_wp_error($disciplines)) { $school = $schools[0]->slug; $discipline = $disciplines[0]->slug; $permalink = str_replace('%schools%', $school, $permalink); $permalink = str_replace('%disciplines%', $discipline, $permalink); } } elseif ($post->post_type == 'courses') { $countries = wp_get_post_terms($post->ID, 'country'); $cities = wp_get_post_terms($post->ID, 'city'); $university = wp_get_post_terms($post->ID, 'universities'); if (!empty($countries) && !empty($cities) && !empty($university)) { $country_slug = $countries[0]->slug; $city_slug = $cities[0]->slug; $university_slug = $university[0]->slug; $permalink = str_replace('%country%', $country_slug, $permalink); $permalink = str_replace('%city%', $city_slug, $permalink); $permalink = str_replace('%university%', $university_slug, $permalink); } } return $permalink; } add_filter('post_type_link', 'custom_post_type_permalink', 10, 3); // Фильтр для изменения ссылок на таксономии function custom_taxonomy_permalink($termlink, $term, $taxonomy) { if ($taxonomy == 'country' || $taxonomy == 'city') { $country = null; $city = null; if ($taxonomy == 'country') { $country = $term->slug; } elseif ($taxonomy == 'city') { $country_term = get_term($term->parent, 'country'); if ($country_term && !is_wp_error($country_term)) { $country = $country_term->slug; } $city = $term->slug; } if ($country) { $termlink = str_replace('%country%', $country, $termlink); } if ($city) { $termlink = str_replace('%city%', $city, $termlink); } } elseif ($taxonomy == 'schools' || $taxonomy == 'disciplines' || $taxonomy == 'universities') { $school = null; $discipline = null; if ($taxonomy == 'schools') { $school = $term->slug; } elseif ($taxonomy == 'disciplines') { $school_term = get_term($term->parent, 'schools'); if ($school_term && !is_wp_error($school_term)) { $school = $school_term->slug; } $discipline = $term->slug; } elseif ($taxonomy == 'universities') { // Для таксономии universities, необходимо сделать дополнительную замену $termlink = str_replace('%university%', $term->slug, $termlink); } if ($school) { $termlink = str_replace('%schools%', $school, $termlink); } if ($discipline) { $termlink = str_replace('%disciplines%', $discipline, $termlink); } } return $termlink; } add_filter('term_link', 'custom_taxonomy_permalink', 10, 3);

Что я ожидал: ccылка ввида universities/%country%/%city%/%university%/courses/курс будет открываться согласно иерархии шаблонов, то есть на странице single-courses.php.
Что я получил:ccылка ввида universities/%country%/%city%/%university%/courses/курс ссылка открывается с ошибкой 404.
Контекст: если изменить ссылку для кастомного типа записи на courses/курс, то будет открываться согласно иерархии шаблонов, то есть на странице single-courses.php, но задача стоит, чтобы страница открывалась по адресу universities/%country%/%city%/%university%/courses/курс.

Вопрос: как правильно присвоить шаблон страницы для кастомного типа записи чтобы он открывался по адресу universities/%country%/%city%/%university%/courses/курс?

Дополнительные вопросы

Попробуйте пересохранить ссылки. Вашу простыню кода тестить не буду, но дам совет — попробуйте сначала добиться, чтобы работал хотя бы один параметр ссылки universities/%country%/, а потом по аналогии добавляйте остальные

Ответы на вопрос 0

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Максим Павлов Ответ

В WordPress нельзя «присвоить шаблон страницы» кастомному типу записи в том же смысле, как обычной странице. Для CPT используются template hierarchy: single-{post_type}.php, archive-{post_type}.php, taxonomy templates и rewrite rules. Если вам нужен URL вида /страна/город/университет/каталог-курсов/курс, задача состоит не в выборе шаблона, а в маршрутизации и связях между CPT.

Я бы разделил задачу на две части:

  1. Какой шаблон отрисовывает курс.
  2. Как WordPress понимает такой длинный URL и находит нужный курс.

Шаблон для CPT courses делается файлом в теме:

single-courses.php

single-courses.php

Если нужно выбирать разные шаблоны внутри одного CPT, можно использовать фильтр:

add_filter('single_template', function ($template) {
    if (is_singular('courses')) {
        $custom = locate_template('single-courses-custom.php');
        if ($custom) {
            return $custom;
        }
    }
    return $template;
});

add_filter('single_template', function ($template) { if (is_singular('courses')) { $custom = locate_template('single-courses-custom.php'); if ($custom) { return $custom; } } return $template; });

Но URL с таксономиями в середине — отдельная история. Нужно добавить rewrite rule и затем подставлять правильный permalink через post_type_link. При этом WordPress должен знать, какой университет связан с курсом, какая страна и город у университета.

Важно: если курс является дочерней сущностью университета, возможно, правильнее хранить связь через post meta или relationship field, а не пытаться сделать всё только таксономиями. Таксономии хорошо подходят для классификации, но не всегда подходят для иерархии объектов.

Минимальная логика маршрута будет примерно такая:

add_action('init', function () {
    add_rewrite_rule(
        '^([^/]+)/([^/]+)/([^/]+)/catalog-courses/([^/]+)/?$',
        'index.php?courses=$matches[4]',
        'top'
    );
});

add_action('init', function () { add_rewrite_rule( '^([^/]+)/([^/]+)/([^/]+)/catalog-courses/([^/]+)/?$', 'index.php?courses=$matches[4]', 'top' ); });

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

Вывод: шаблон — это single-courses.php или фильтр single_template. А желаемый адрес делается через rewrite + permalink filter + проверку связей. Без этой проверки будет много дублей.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

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

Вам также может быть интересно