WordPress как на ладони
Недорогой хостинг для сайтов на WordPress: wordpress.jino.ru

Вывод архивов подкатегорий в соответствии с их уровнем вложенности

На сайте настроены постоянные ссылки по принципу /%category%/%postname%/. Когда я перехожу на какую-то запись из подкатегории, допустим, третьего уровня вложенности, в адресной строке получаю:

https://mysite.ru/news/russia/economy/name-of-article/

И, соответственно, в "хлебных крошках" это выглядит как:

Главная / Новости / Россия / Экономика / Название материала

Всё здорово - так и задумывалось. Но проблема заключается в том, что при попытке открыть https://mysite.ru/news/russia/economy/ или https://mysite.ru/news/russia/ я получаю ошибку 404. Хотя предполагаю увидеть там список материалов соответствующей подкатегории.

При этом по адресу https://mysite.ru/economy/ или https://mysite.ru/russia/ всё прекрасно выводится. То есть от корня каждая подкатегория работает, а при любом уровне вложенности - нет.

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

Подскажите, есть ли какой-то иной способ выводить материалы подкатегорий с помощью одного шаблона archive.php, но в соответствии с их уровнями вложенности?

0
Наум
1 месяц назад
  • 0
    Kama8418

    Такое сделать можно, но сложно. Вот нечто подобное https://wp-kama.ru/id_7637/chpu-dlya-treh-taksonomij-i-tipa-zapisi-odnovremenno.html

    Чтобы такое реализовать, нужно изменить правила обработки URL для рубрик, без хорошего знания как все это работает в ВП, сам не сделаешь думаю.

    Правильнее всего наверное будет обратится к тому кто сможет такое сделать или попробовать найти готовое решение в интернете.

    Я бы помог, но время нет, за отдельную плату только если да и то не сразу...

    П.С. предложенные тобой костыли - это не вариант вообще!

    Комментировать
  • 1

    Держи готовое решение для постов и категорий. Единственное - не ручаюсь, что оно рабочее для всех случаев, сделал недавно, толком не оттестировал:

    /**
     * Генерируем правила рерайтов для всех категорий
     */
    function generate_cat_rewrites()
    {
    	$cats = get_categories( ['hide_empty' => false, 'fields' => 'ids'] );
    
    	foreach ( $cats as $cat )
    	{
    		$struct = trim( get_category_parents( $cat, false, '/', true ), '/' );
    
    		add_rewrite_rule( "({$struct})/?$", 'index.php?category_name=$matches[1]', 'top' );
    		add_rewrite_rule( "({$struct})/page/?([0-9]{1,})/?$", 'index.php?category_name=$matches[1]&paged=$matches[2]', 'top' );
    	}
    }
    add_action( 'init', 'generate_cat_rewrites' );
    
    /**
     * При взаимодействиями с категориями сбрасываем рерайты
     */
    add_action( 'created_category', 'flush_rewrite_rules' );
    add_action( 'edited_category', 'flush_rewrite_rules' );
    add_action( 'deleted_category', 'flush_rewrite_rules' );
    
    /**
     * Убираем базу категории из ЧПУ
     *
     * @param string $url
     */
    function remove_category_base( $url )
    {
    	$base = get_option( 'category_base' ) ?: 'category';
    
    	return str_replace( trailingslashit( $base ), '', $url );
    }
    add_filter( 'category_link', 'remove_category_base' );
    
    /**
     * Добавляет структуру категорий к ЧПУ поста
     *
     * @param string $post_link
     * @param object $post
     */
    function add_cats_struct_to_post( $post_link, $post )
    {
    	if ( false !== strpos( $post_link, '%category%' ) && 'post' === get_post_type( $post ) && 'auto-draft' !== $post->post_status )
    	{
    		$struct    = get_post_category_struct( $post->ID );
    		$post_link = str_replace( '/%category%/', $struct, $post_link );
    	}
    
    	return $post_link;
    }
    add_filter( 'pre_post_link', 'add_cats_struct_to_post', 10, 2 );
    
    /**
     * Выбирает самую "нижнюю" категорию из массива объектов категорий
     *
     * @param array $cats
     */
    function get_deepest_child_category( $cats )
    {
    	$max_id = 0;
    	$index  = 0;
    
    	foreach ( $cats as $i => $cat )
    	{
    		if ( $cat->parent >= $max_id )
    		{
    			$max_id = $cat->term_id;
    			$index  = $i;
    		}
    	}
    
    	return $cats[$index]->term_id;
    }
    
    /**
     * Строит структуру ЧПУ для поста
     *
     * @param int $post_id
     */
    function get_post_category_struct( $post_id )
    {
    	$cat    = get_deepest_child_category( wp_get_object_terms( $post_id, 'category', ['fields' => 'all'] ) );
    	$struct = get_category_parents( $cat, false, '/', true );
    
    	return $struct;
    }
    Наум 1 месяц назад

    у меня, к сожалению, этот код не заработал

    Jackky 1 месяц назад

    Напиши, какие ошибки, почему не заработал? Давай помогу, разберёмся

    PS: ты не забыл пересохранить структуру ссылок в админке /wp-admin/options-permalink.php?

    Kama 1 месяц назад

    А если там 1000 рубрик, в правилах будет 1000 регулярок? Хм...

    Jackky 1 месяц назад

    Да, я в курсе, но по-другому избавится от category префикса не знаю как. Расчёт на то, что категорий редко когда больше 100 бывает, а то и больше 20 и тогда это решение норм вполне.

    Комментировать
На вопросы могут отвечать только зарегистрированные пользователи. Вход . Регистрация