falbar Удаляем дубли WordPress

Удаляем дубли WordPress

24 января 2018 1192 7

Есть зло, которое уже давно живет в WordPress, и сегодня мы попробуем его побороть! Это зло – дубли. Наш любимый движок, может доставить массу проблем, плодя бесполезные страницы. Лечиться этот недуг просто добавлением нескольких строк кода, которые избавят владельцев сайтов от лишней головной боли в дальнейшем.

Реклама

Когда мы только установили WordPress или пришли к выводу, что у нас есть страницы, которые не хотелось бы видеть в выдаче, то мы можем решить эту задачу несколькими способами. Первый - это воспользоваться файликом robots.txt – это удалит страницы из индекса, но они останутся доступны для наших посетителей. Мало кому взбредёт сослаться на закрытые страницы, то нам от этого пользы будет мало, поэтому есть второй способ – это воспользоваться WordPress API, при помощи, которого мы можем закрыть страницы и установить необходимые редиректы.

Основные дубли в WordPress, с которыми мы можем столкнуться это:

  • Страницы вложений – под каждый загруженный файл или изображение генерируется полноценная страница с формой. Мало того, что в большинстве случаев она сама лишний груз, так ещё через форму комментирования мы можем получить нескончаемый поток спама;
  • Архивы дат – с одной стороны полезная штука, но мы получаем три страницы с одним и тем же контентом (/год/, /год/месяц/, /год/месяц/день/) - это большой минус, который надо обязательно устранять;
  • Пагинация у статей – как по мне, бесполезный функционал, который только размазывает контент;
  • ?replytocom – в комментариях к ссылке ответить добавляется эта часть, раньше это было страшной бедой, так как если статья была обсуждаема, то мы получали на неё десяток и более дублей.

Для того, чтобы избавиться от этих дублей в WordPress, нам потребуется открыть файл functions.php в активной теме и добавить туда код. Давайте будем работать поочередно и сперва разберемся со страницами вложений, для этого добавим следующие строчки:

add_action('template_redirect', 'remove_attachment_pages', 1);

function remove_attachment_pages(){

	global $post;

	$post_parent = $post->post_parent;

	if(!isset($post_parent) || !is_numeric($post_parent)){

		return false;
	}

	if(is_attachment() && $post_parent != 0){

		$page_url = get_permalink($post_parent);
		$status	  = 301;
	}else if(is_attachment() && $post_parent < 1){

		$page_url = get_home_url();
		$status   = 302;
	}else{

		return false;
	}

	wp_safe_redirect(
		esc_url_raw(
			apply_filters(
				'sitecare_redirect_unattached_images',
				$page_url
			)
		),
		$status
	);

	exit();
}

Мы прикрепляем к событию template_redirect свою функцию, в которой устанавливаем редирект при открытии страницы с файлом или изображением. Так же, если вложение не прикреплено к контентной странице, перенаправляем пользователя на главную.

Двигаемся дальше и разберемся с архивами. Принцип тот же, только мы прикрепляем свою функцию к событию wp:

add_action('wp', 'remove_archives_date');

function remove_archives_date(){

	if(is_date() && !is_admin()){

		wp_redirect(
			get_home_url(),
			301
		);

		exit();
	}

	return false;
}

Для того, чтобы избавиться от пагинации у постов нам потребуется добавить следующий код:

add_action('template_redirect', 'remove_post_pagination');

function remove_post_pagination(){

	if(is_singular() && !is_front_page()){

		global $post, $page;

		$num_pages = substr_count($post->post_content, '<!--nextpage-->') + 1;

		if($page > $num_pages || $page == 1){

			wp_redirect(
				get_permalink($post->ID)
			);

			exit();
		}
	}

	return false;
}

Чтобы решить проблему с дублями ?replytocom, нам потребуется установить редирект и, дополнительно, убрать параметр у самих ссылок:

dublyami-replytocom

Добавляем перенаправление на саму же статью:

add_action('template_redirect', 'remove_replytocom', 1);

function remove_replytocom(){

	if(isset($_GET['replytocom']) && is_singular()){

		$post_url 	  = get_permalink($GLOBALS['post']->ID);
		$comment_id   = sanitize_text_field($_GET['replytocom']);
		$query_string = remove_query_arg(
			'replytocom',
			sanitize_text_field(
				$_SERVER['QUERY_STRING']
			)
		);

		if(!empty($query_string)){

			$post_url .= '?'.$query_string;
		}

		$post_url .= '#comment-'.$comment_id;

		wp_redirect($post_url, 301);

		exit();
	}

	return false;
}

И вырезаем сомнительный параметр из ссылки:

add_filter('comment_reply_link', 'link_remove_replytocom');

function link_remove_replytocom($link){

	return preg_replace(
		'`href=(["\'])(?:.*(?:\?|&|&#038;)replytocom=(\d+)#respond)`',
		'href=$1#comment-$2',
		$link
	);
}
dublyami-replytocom-somnitelnyj-parametr

Вот и всё, мы получили нормальную ссылку на форму с ответом.

Как вы могли заметить мы смогли довольно легко залатать дыры в нашем движке и для этого нам потребовалось немного расширить наш functions.php, но это не самый лучший вариант! Третий способ – это установить соответствующий плагин. Так как если нам потребуется создать новый проект, то весь код придётся копипастить и добавлять заново, а его только для удаления дублей получилось строк 100. Для решения это задачи, а также чистки кода и оптимизации WordPress я написал собственный плагин Bicycles by falbar, где более 30+ объединённых в одном месте велосипедов.

Реклама
aleks
27 января 2018
Можно ли применить этот код к ссылкам вида сайт/no_redirect=true или как от них избавиться
Антон Кулешов
28 января 2018
Код из статьи решает проблемы связанные со стандартным функционалом WordPress, но можно привязаться к событию init и перед выводом страницы вырезать эту часть ссылки.
aleks
28 января 2018
Эти ссылки появились только в вебмастере яндекса на все посты, рубрики и главную. Откуда и почему могут возникать ссылки с - /?no_redirect=true. Если можно пример кода для удаления.
В интернете ответа не нашел
Антон Кулешов
28 января 2018
Как я понял, на страницы вашего сайта можно перейти из вебмастера с параметром no_redirect. Решить эту проблему можно установив 301 ридирект на страницу уже без параметра. Делается это таким образам:

add_action('init', 'init_remove_no_redirect');

function init_remove_no_redirect(){

if(!empty($_GET['no_redirect'])){

$url = remove_query_arg(
'no_redirect',
$_SERVER['REQUEST_URI']
);

wp_redirect($url, 301);

exit();
}

return false;
}
aleks
28 января 2018
Спасибо за помощь! Буду пробывать
aleks
28 января 2018
Большущее спасибо!!! Все получилось, код пришлось вставить в самое начало functions, вставлял в конце, не работает.
Антон Кулешов
28 января 2018
Странно, что в конце не работает. Видимо что-то перебивает.
no_avatar