WordPress как на ладони

БАГ: Дубли страниц категорий — разные URL для одной и той же Рубрики (термина таксономии)

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

Например, рубрика доступна по адресам:

Я так понимаю это проблема всего вордпресс, можно ли как-то решить проблему, чтобы рубрики были доступны по 1 url-адресу? А остальные адреса отдавали 404. Спасибо.

1
ВЛАДИМИР
1.2 года назад
  • 2
    Kama8765

    Да это проблема WP. И что странно по дефолту даже канонических ссылок нет в HEAD.

    Решить можно таким хаком:

    add_action( 'template_redirect', 'check_301redirect_tax_url', 9 );
    function check_301redirect_tax_url(){
    
    	// not taxonomy
    	if( ! ( is_category() || is_tag() || is_tax() ) )
    		return;
    
    	$qo = get_queried_object();
    
    	$term_url = get_term_link( $qo );
    	$parsed_url = parse_url( $_SERVER['REQUEST_URI'] );
    
    	if( strpos( $parsed_url['path'], wp_make_link_relative( $term_url ) ) === false ){
    		$redirect_to = isset( $parsed_url['query'] ) ? "$term_url?{$parsed_url['query']}" : $term_url;
    		wp_redirect( $redirect_to, 301 );
    		exit;
    	}
    
    }
    DimaDV 5 месяцев назад

    Спасибо. Помогло!

    Алексей 2 месяца назад

    Данная функция не работает. Но проблема актуальна.

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

    Проверил код - работает отлично - редиректит с кривого на нормальный УРЛ. Как он может не работать я даже не знаю. Может вы код куда-то не туда вставили? В functions.php добавь его, а не в какой-нить файл шаблона...

    Алексей 2 месяца назад

    Перепроверил. Код по прежнему не работает.
    Но я заметил, что url категорий создается не стандартно.

    Например рубрика news и в ней дочерняя рубрика sport

    И у меня получился адрес site.com/sport

    При всём при этом существует страница
    site.com/news/sport
    site.com/любой текст/sport
    site.com/category/news/sport

    Задача сделать переадресацию всех этих дублеров на site.com/sport

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

    Что то у тебя там не то. Проверь что возвращает эта проверка на странице такой рубрики: var_dump( is_category() || is_tag() || is_tax() ). Видимо её код не проходит, а должен!

    Также проверь что возвращает это: $qo = get_queried_object();

    Алексей 2 месяца назад

    Нашел на сайте активный старый код и отредактировал.
    Получилось по умолчанию ссылки открываются так: site.com/category/news/sport

    и

    site.com/category/news/sport - работает
    site.com/news/sport - 404 ошибка
    site.com/sport - работает

    если вставить функцию check_301redirect_tax_url

    то с site.com/sport переадресует на site.com/category/news/sport

    Только надо наоборот, чтобы site.com/sport был по умолчанию и всё остальное переадресовало на аналогичный адрес.

    var_dump( is_category() || is_tag() || is_tax() )

    выводит

    bool(true)

    а

    $qo = get_queried_object(); 

    ничего не выводит

    Алексей 2 месяца назад

    Сейчас всё идеально работает вместе с функцией check_301redirect_tax_url
    Только основной url получился site.com/category/news/sport и соответственно редирект введет на этот адрес.

    Как сделать чтобы все рубрики были по умолчанию такие как site.com/sport ??

    Алексей 2 месяца назад

    Хак check_301redirect_tax_url не совместим с плагином No category parents в моем случае это был бы идеальный симбиоз.

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

    Не знаю как работает No category parents, но это неправильно что для get_term_link() он отдает ссылку с деревом родителей - site.com/category/news/sport, должен отдавать site.com/news/sport. По идее дерево можно удалить используя хук term_link.

    В подробности вдаваться не буду, потому что хз что там в коде плагина и почему он сам это не делает - очень странно.

    Алексей 2 месяца назад

    Он так не делал, потому что я плагин отредактировал. Сейчас откатил на первоначалку. Получилось как писал в начале.

    Главная страница site.com/sport

    При всём при этом существует страница
    site.com/news/sport
    site.com/любой текст/sport
    site.com/category/news/sport

    Все страницы работают исправно.

    Но хак check_301redirect_tax_url не делает редирект.

    С чем это связано?

    Алексей 2 месяца назад

    Вот сам плагин:

    add_filter ("pre_post_link", "filter_category");            // will apply to post permalink
    add_filter ("user_trailingslashit", "myfilter_category");
    
    add_filter ("category_link", "filter_category_link");           // will apply to post permalink
    
    add_filter( 'rewrite_rules_array','my_insert_rewrite_rules' );
    add_filter( 'query_vars','my_insert_query_vars' );
    add_action( 'wp_loaded','my_flush_rules' );
    
    // seems category filters are not working
    add_action('created_category','my_flush_rules2');
    add_action('edited_category','my_flush_rules2');
    add_action('delete_category','my_flush_rules2');
    
    // flush_rules() if our rules are not yet included
    function my_flush_rules(){
    	update_option('category_base','');
    	$rules = get_option( 'rewrite_rules' );
    
    	//if ( ! isset( $rules['(.+?)-cat/?$'] ) ) { // have to comment this in order to refresh the rules
    		global $wp_rewrite;
    		$wp_rewrite->flush_rules();
    	//}
    }
    
    function my_flush_rules2(){
    	$rules = get_option( 'rewrite_rules' );
    
    		global $wp_rewrite;
    		$wp_rewrite->flush_rules();
    }
    
    // Adding a new rule
    function my_insert_rewrite_rules( $rules )
    {
    global $wp_rewrite;
    	$newrules = array();
    	$newrules['(.+?)-cat/?$'] = 'index.php?category_name=$matches[1]';
    	$newrules['(.+?)-cat/'.$wp_rewrite->pagination_base.'/?([0-9]{1,})/?$'] = 'index.php?category_name=$matches[1]&paged=$matches[2]';
    
    	$categories = get_categories(array('hide_empty'=>false));
    
    	if ($categories)
    	{
    		foreach ($categories as $key => $val)
    		{
    			$posts = get_posts (array("name" => $val->slug));       
    			if (!$posts)
    			{
    				$newrules['('.$val->category_nicename.')/?$'] = 'index.php?category_name=$matches[1]';
    				$newrules['('.$val->category_nicename.')/'.$wp_rewrite->pagination_base.'/?([0-9]{1,})/?$'] = 'index.php?category_name=$matches[1]&paged=$matches[2]';
    
    				$newrules['.+?/('.$val->category_nicename.')/?$'] = 'index.php?category_name=$matches[1]';
    				$newrules['.+?/('.$val->category_nicename.')/'.$wp_rewrite->pagination_base.'/?([0-9]{1,})/?$'] = 'index.php?category_name=$matches[1]&paged=$matches[2]';
    			}
    		}
    	}
    
    	return $newrules + $rules;
    }
    
    function my_insert_query_vars( $vars )
    {
    	array_push($vars, 'id');
    	return $vars;
    }
    
    //add_filter('request', 'mycategory_rewrite_rules');
    
    function mycategory_rewrite_rules() {
    	global $wp_rewrite;
    
    	echo "<pre>";
    	print_r ($wp_rewrite);
    	echo "</pre>";
    
    //  [(.+?)/?$] => index.php?category_name=$matches[1]
    
    }
    
    function filter_category_link ($termlink)
    {
    	if (preg_match ("/\?cat=/", $termlink))
    		return $termlink;
    
    	$str = explode("/", $termlink);
    
    	$myslug = $slug = $str[count($str)-2];
    
    	// check if category slug exist in post
    
    	$posts = get_posts (array("name" => $slug));        
    	preg_match ("/category.*?".$myslug."/", $termlink, $result);
    
    	if ($posts)
    		$slug .= "-cat";
    
    	$str = explode("/", $result[0]);
    
    	if (count($str) > 3)
    		$link = $str[count($str)-2]."/".$slug ;     
    	else
    		$link = $slug;
    
    	$termlink = preg_replace ("/category.*?".$myslug."/", $link, $termlink);
    
    	return $termlink;   
    }
    
    function filter_category ($permalink)
    {
    	$permalink = str_replace ("%category%", "%mycategory%", $permalink); 
    
    	return $permalink;
    }
    
    function myfilter_category ($string)
    {
    	if (preg_match ("/%mycategory%/", $string))
    	{
    		$str = explode("/", $string);
    		$slug = $str[count($str)-2];
    
    		$posts = get_posts (array("name" => $slug));
    
    		$cats = get_the_category($posts[0]->ID);
    
    		if ( $cats ) {
    			usort($cats, '_usort_terms_by_ID'); 
    			$category = $cats[0]->slug;
    			if ( $parent = $cats[0]->parent )
    			{
    				$one = 1;
    			}
    		}
    
    		$string = preg_replace("/%mycategory%/", $category, $string);       
    	}
    
    	return $string; 
    }
    Kama 2 месяца назад

    Извиняй, нет времени разбираться, то что выше писал еще раз проверь с включенным этим кодом.

    П.С. Вот это дикий хук ваще add_action( 'wp_loaded','my_flush_rules' ); - на каждом запросе же срабатывает...

    Алексей 2 месяца назад

    Хорошо, пофиг на самом деле на этот плагин. Как сделать чтобы был вот такой юрл:

    site.com/news/sport

    и работал хак check_301redirect_tax_url

    ??

    Крч всё как здесь wp-kama.ru smile

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

    Я вообще не понимаю зачем нужно префикс удалять. Он же удобен и для сео вроде как лучше. Поисковик может как-то каталогизировать УРЛы. Все которые с одинаковым префиксом он поймет что относятся к одному типу, например тут это рубрики. А если префикс убрать, то ничем же не будет отличаться от страниц. Неужели ты хочешь чтобы поисковики видели отдельные страницы так же как и категории. Я хз, может когда-то это нужно, но я даже не знаю когда, все должно быть понятно и очевидно и не надо лишний раз ничего выдумывать, при этом усложняя код, добавляя хуки адские как в примере выше.

    То что ты просишь можно сделать, но у меня нет готового решения нормального, а писать его сча я не хочу, отчасти и потому что считаю это ненужным вообще занятием. С префиксом по-моему даже лучше и если бы его не было, его бы стоило добавить наоборот ИМХО.

    Алексей 2 месяца назад

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

    anonym 2 месяца назад

    я так понимаю для страницы товара нужно вместо

    if( ! ( is_category() || is_tag() || is_tax() ) )

    вставить

    if( ! ( is_product() ) )

    но при такой конструкции происходит редирект на страницу
    сайт.ру/?taxonomy=&term=

    или поскажите как сделать чтобы при таком урле сайт.ру/категория/праовлоы/товар был редирект на 404 страницу

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

    я так понимаю для страницы товара нужно вместо

    https://wp-kama.ru/question/dubli-tovarov-woocommerce там ответил.

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