@DarkFlame77

Как добавить поддержку древовидной таксономии у пользовательских типов?

Доброго времени.
Суть проблемы:
Нужно реализовать каталог основанный на пользовательских типах и таксономиях. нужны УРЛы типа:
site.ru/catalog/ - выводятся все продукты.
site.ru/catalog/term/ - выводятся продукты привязанные к терму.
site.ru/catalog/term/product/ - страничка продукта(кастомный тип поста).
site.ru/catalog/term/subterm/ - выводятся продукты привязанные к subterm.
site.ru/catalog/term/subterm/product/ - страничка продукта(кастомный тип поста).
site.ru/catalog/term/subterm/subsubterm/product/ - страничка продукта(кастомный тип поста).
Ну и т.д.

Второй день ищу решение этой проблемы, но никак не могу найти. Интересно, что дефолтная такса "рубрики(category)" работает именно так как требуется мне. А вот пользовательскую не могу реализовать с таким же функционалом.

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

На данный момент код выглядит так.
////////////////////////////////////////////////
add_action( 'init', 'register_faq_post_type' );
function register_faq_post_type() {
	register_taxonomy('catalogs', array('products'), array(
		'label'                 => 'Раздел каталога', 
		'labels'                => array(
			'name'              => 'Разделы каталога',
			'singular_name'     => 'Раздел каталога',
			'search_items'      => 'Найти раздел каталога',
			'all_items'         => 'Все разделы каталога',
			'view_item '        => 'Показать раздел каталога',
			'parent_item'       => 'Родительский раздел каталога',
			'parent_item_colon' => 'Родительский раздел каталога:',
			'edit_item'         => 'Редактировать раздел каталога',
			'update_item'       => 'Обновить раздел',
			'add_new_item'      => 'Добавить новый раздел',
			'new_item_name'     => 'Новое имя раздела',
			'menu_name'         => 'Разделы каталога',
		),
		'description'           => 'Разделы каталога', 
		'public'                => true,
		'show_in_nav_menus'     => false, 
		'show_ui'               => true, 
		'show_tagcloud'         => false,
		'hierarchical'          => true,
		'rewrite'               => array('slug'=>'catalog', 'hierarchical'=>true, 'with_front'=>false, 'feed'=>false ),
		'show_admin_column'     => true, 
	) );

	register_post_type('products', array(
		'label'               => 'Продукция',
		'labels'              => array(
			'name' => 'Продукция',
			'singular_name' => 'Продукт',
			'add_new' => 'Новый продукт',
			'add_new_item' => 'Добавить новый продукт',
			'edit_item' => 'Редактировать продукт',
			'new_item' => 'Новый продукт',
			'view_item' => 'Просмотреть продукт',
			'search_items' => 'Найти продукт',
			'not_found' =>  'Продукты не найдены',
			'not_found_in_trash' => 'В корзине продуктов нет'
		),
		'description'         => '',
		'public'              => true,
		'publicly_queryable'  => true,
		'show_ui'             => true,
		'show_in_rest'        => false,
		'rest_base'           => '',
		'show_in_menu'        => true,
		'exclude_from_search' => false,
		'capability_type'     => 'post',
		'map_meta_cap'        => true,
		'hierarchical'        => false,
		'rewrite'             => array( 'slug'=>'catalog/%catalogs%', 'with_front'=>false, 'hierarchical' => true, 'pages'=>false, 'feeds'=>false, 'feed'=>false ),
		'has_archive'         => 'catalog',
		'query_var'           => true,
		'supports'            => array( 'title', 'editor' ),
		'taxonomies'          => array( 'catalogs' ),
	) );

}


function filter_post_type_link($link, $post) {
	if ($post->post_type != 'products')
		return $link;

	if ($cats = get_the_terms($post->ID, 'catalogs'))
		$link = str_replace('%catalogs%', array_pop($cats)->slug, $link);
	return $link;
}
add_filter('post_type_link', 'filter_post_type_link', 10, 2);


function default_taxonomy_term( $post_id, $post ) {
	if ( 'publish' === $post->post_status ) {
		$defaults = array(
			'catalogs' => array('non-cat'),
		);
		$taxonomies = get_object_taxonomies( $post->post_type );
		foreach ( (array) $taxonomies as $taxonomy ) {
			$terms = wp_get_post_terms( $post_id, $taxonomy );
			if ( empty( $terms ) && array_key_exists( $taxonomy, $defaults ) ) {
				wp_set_object_terms( $post_id, $defaults[$taxonomy], $taxonomy );
			}
		}
	}
}
add_action( 'save_post', 'default_taxonomy_term', 100, 2 );
  • Вопрос задан
  • 110 просмотров
Пригласить эксперта
Ответы на вопрос 1
@DarkFlame77 Автор вопроса
в общем добавил древовидную структуру, немного переделав фильтр.
function filter_post_type_link($link, $post) {
	if ($post->post_type != 'products')
		return $link;
	if ($cats = get_the_terms($post->ID, 'catalogs'))		
		$parent_slug =  get_term_parents_list($cats[0]->term_id, 'catalogs', array(
			'separator' => '/',
			'format'    => 'slug',
			'link'      => false,
			'inclusive' => true,
		) );
		$parent_slug = mb_substr($parent_slug, 0, -1);		
		$link = str_replace('%catalogs%', $parent_slug, $link);
	return $link;
}
add_filter('post_type_link', 'filter_post_type_link', 10, 2);

осталось решить проблему с общей базой.
Нужна база - catalog и для такс и для постов. т.е. вот этот пример
site.ru/catalog/term/subterm/ - выводятся продукты привязанные к subterm.
site.ru/catalog/term/subterm/product/ - страничка продукта(кастомный тип поста).

Сейчас если rewrite делать не с общей базой catalog, то все работает как надо и открываются и разделы/подразделы и сам товар, но разная база портит цельность структуры. И в хлебных крошках тоже выглядит это не очень хорошо.

UP.
В общем вроде бы получил конечное решение. Может кому-то пригодится. Так же прошу людей хорошо разбирающихся в теме указать на ошибки, подводные камни такого решения или возможно предложить более правильное. Мое такое получилось:
////////////////////////////////////////////////
add_action( 'init', 'register_faq_post_type' );
function register_faq_post_type() {
	register_taxonomy('catalogs', array('products'), array(
		'label'                 => 'Раздел каталога', 
		'labels'                => array(
			'name'              => 'Разделы каталога',
			'singular_name'     => 'Раздел каталога',
			'search_items'      => 'Найти раздел каталога',
			'all_items'         => 'Все разделы каталога',
			'view_item '        => 'Показать раздел каталога',
			'parent_item'       => 'Родительский раздел каталога',
			'parent_item_colon' => 'Родительский раздел каталога:',
			'edit_item'         => 'Редактировать раздел каталога',
			'update_item'       => 'Обновить раздел',
			'add_new_item'      => 'Добавить новый раздел',
			'new_item_name'     => 'Новое имя раздела',
			'menu_name'         => 'Разделы каталога',
		),
		'description'           => 'Разделы каталога', 
		'public'                => true,
		'show_in_nav_menus'     => false,
		'show_ui'               => true, 
		'show_tagcloud'         => false, 
		'hierarchical'          => true,
		'rewrite'               => array('slug'=>'catalog', 'hierarchical'=>true, 'with_front'=>false, 'feed'=>false ),
		'show_admin_column'     => true, 
	) );

	register_post_type('products', array(
		'label'               => 'Продукция',
		'labels'              => array(
			'name' => 'Продукция',
			'singular_name' => 'Продукт',
			'add_new' => 'Новый продукт',
			'add_new_item' => 'Добавить новый продукт',
			'edit_item' => 'Редактировать продукт',
			'new_item' => 'Новый продукт',
			'view_item' => 'Просмотреть продукт',
			'search_items' => 'Найти продукт',
			'not_found' =>  'Продукты не найдены',
			'not_found_in_trash' => 'В корзине продуктов нет'
		),
		'description'         => '',
		'public'              => true,
		'publicly_queryable'  => true,
		'show_ui'             => true,
		'show_in_rest'        => false,
		'rest_base'           => '',
		'show_in_menu'        => true,
		'exclude_from_search' => false,
		'capability_type'     => 'post',
		'map_meta_cap'        => true,
		'hierarchical'        => false,
		'rewrite'             => array('slug'=>'products/%catalogs%'),
		'has_archive'         => 'catalog',
		'query_var'           => true,
		'supports'            => array( 'title', 'editor' ),
		'taxonomies'          => array( 'catalogs' ),
	) );

}


function filter_post_type_link($link, $post) {
	if ($post->post_type != 'products')
		return $link;
	if ($cats = get_the_terms($post->ID, 'catalogs'))		
		$parent_slug =  get_term_parents_list($cats[0]->term_id, 'catalogs', array(
			'separator' => '/',
			'format'    => 'slug',
			'link'      => false,
			'inclusive' => true,
		) );
		$parent_slug = mb_substr($parent_slug, 0, -1);		
		$link = str_replace('%catalogs%', 'catalog/'.$parent_slug, $link);
	return $link;
}
add_filter('post_type_link', 'filter_post_type_link', 10, 2);


function default_taxonomy_term( $post_id, $post ) {
	if ( 'publish' === $post->post_status ) {
		$defaults = array(
			'catalogs' => array('non-cat'),
		);
		$taxonomies = get_object_taxonomies( $post->post_type );
		foreach ( (array) $taxonomies as $taxonomy ) {
			$terms = wp_get_post_terms( $post_id, $taxonomy );
			if ( empty( $terms ) && array_key_exists( $taxonomy, $defaults ) ) {
				wp_set_object_terms( $post_id, $defaults[$taxonomy], $taxonomy );
			}
		}
	}
}
add_action( 'save_post', 'default_taxonomy_term', 100, 2 );




function na_remove_slug( $post_link, $post, $leavename ) {

    if ( 'products' != $post->post_type || 'publish' != $post->post_status ) {
        return $post_link;
    }

    $post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link );

    return $post_link;
}
add_filter( 'post_type_link', 'na_remove_slug', 10, 3 );

function na_parse_request( $query ) {

    if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
        return;
    }

    if ( ! empty( $query->query['name'] ) ) {
        $query->set( 'post_type', array( 'post', 'products', 'page' ) );
    }
}
add_action( 'pre_get_posts', 'na_parse_request' );
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы