Вопрос или проблема
На сайте WordPress http://www.example.com/
(ГЛАВНЫЙ САЙТ) более 540000 постов.
Я хочу уменьшить количество постов, чтобы повысить скорость сайта.
Я установил новый WordPress на http://www.example.com/business-consultants/
(НОВЫЙ САЙТ) и перенес с ГЛАВНОГО САЙТА 3135 постов с тегом ‘Business Consultants’.
В настоящее время я настроил 301 редирект на ГЛАВНОМ САЙТЕ, чтобы перенаправлять посты с тегом ‘Business Consultants’ на новую установку WordPress, то есть
{MAIN_SITE}/{slug} => {NEW_SITE}/business-consultants/{slug}
Что я делаю, так это проверяю тег поста, и если присутствует ‘business-consultants’, перенаправляю запрос на новый сайт, используя wp_safe_redirect()
.
Проблема в том, что для того, чтобы редирект работал, посты должны быть на ГЛАВНОМ САЙТЕ, и я ищу решение, которое позволит делать редирект даже если посты с тегом ‘Business Consultants’ удалены с главного сайта.
Это сложная задача.
Что я предлагаю – запустить одноразовое задание, которое:
- получает все посты с тегом ‘business-consultants’
- запускает одноразовое задание*, чтобы сохранить в php-файл массив этих слагов постов
- когда запрашивается один из этих URL, перенаправляет на новый URL сайта
- удаляет посты
Я напишу весь код в виде плагина.
Я настоятельно рекомендую вам сделать полную резервную копию вашей базы данных перед установкой этого плагина
Сохраните следующий код в файле с именем RedirectDeleted.php
, поместите в папку плагинов и активируйте его.
Это займет несколько секунд перед полной загрузкой страницы, но после этого, если вы перейдете на страницу списка ваших постов, вы должны увидеть все посты с тегом ‘business-consultants’, удаленные из WordPress, а также в вашей папке загрузок вы должны увидеть файл php с именем redirect_deleted_business-consultants.php
.
Если вы когда-либо зайдете по URL, как http://www.example.com/a-post-slug
(где ‘a-post-slug’ — это настоящий слаг поста с тегом ‘business-consultants’), вы должны быть перенаправлены на http://www.example.com/business-consultants/a-post-slug
.
Обратите внимание, что если вы когда-либо удалите файл redirect_deleted_business-consultants.php
или удалите плагин, редирект больше не будет работать.
Установка плагина в качестве обязательного плагина может быть идеей, чтобы предотвратить удаление.
Например, если у вас есть тег со слагом ‘business-stuff’ и вы хотите перенести его на другую установку WP, просто создайте эту установку по URL http://www.example.com/business-stuff
и добавьте ‘business-stuff’ в файл плагина в массив $target_tags
(см. ниже).
Код:
<?php
/**
* Название плагина: RedirectDeletedTag
* URI плагина: https://wordpress.stackexchange.com/questions/136018/
*/
class RedirectDeletedTag {
/**
* Измените эту переменную в соответствии с реальным слагом тега.
* Ключ - это слаг тега, а значение - базовый URL для редиректа.
* Если хотите, вы можете добавить другие слаги тегов, которые хотите перенести на отдельные сайты.
*/
protected $target_tags = array(
'business-consultants' => 'http://www.example.com/business-consultants/',
);
function cacheUrls() {
if ( ! is_admin() || ! current_user_can( 'install_plugins' ) ) return;
$t = new ArrayIterator( $this->target_tags );
while( $t->valid() ) {
$tag = $t->key();
if ( $this->shouldCache( $tag ) ) $this->cacheTagUrls( $tag );
$t->next();
}
}
function redirect() {
if ( is_admin() ) return;
$url = $this->getUrl();
if ( ! empty( $url ) ) {
$t = new ArrayIterator( $this->target_tags );
while( $t->valid() ) {
$this->redirectTag( $t->key(), $url, $t->current() );
$t->next();
}
}
}
protected function cacheTagUrls ( $tag ) {
$args = array( 'post_type' => 'post', 'nopaging' => true, 'tag' => $tag );
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
$slugs = wp_list_pluck( $query->posts, 'post_name' );
$id_list = implode( ',', wp_list_pluck( $query->posts, 'ID') );
$cache="<?php return array("" . implode('","', $slugs ) . '");';
if ( @file_put_contents( $this->getCachePath( $tag ), $cache ) !== FALSE ) {
set_transient( __CLASS__ . $tag, '1' );
// кэш сохранен, удалите все посты и термины
global $wpdb;
$wpdb->query( "DELETE FROM $wpdb->posts WHERE ID IN ($id_list)" );
$term = get_term_by('slug', $tag, 'post_tag');
if ( ! empty( $term ) && isset( $term->term_id ) ) {
wp_delete_term( $term->term_id, 'post_tag' );
}
}
}
}
protected function redirectTag( $tag, $url, $base ) {
if ( file_exists( $this->getCachePath( $tag ) ) ) {
$cached = (array) include $this->getCachePath( $tag );
if ( in_array( $url, $cached ) ) {
wp_redirect( trailingslashit( $base ) . $url );
exit();
}
}
}
protected function shouldCache( $tag = '' ) {
$should = FALSE;
if ( is_admin() && current_user_can( 'install_plugins' ) ) {
$transient = get_transient( __CLASS__ . $tag );
$file = file_exists( $this->getCachePath( $tag ) );
$should = empty($transient) && ! $file;
}
return $should;
}
protected function getCachePath( $tag = '' ) {
$upload_dir = wp_upload_dir();
$base = trailingslashit( $upload_dir['basedir'] );
return $base . 'redirect_deleted_' . $tag . '.php';
}
protected function getUrl() {
$home_path = trim( parse_url( home_url(), PHP_URL_PATH ), "https://wordpress.stackexchange.com/" );
$full = trim( str_replace( $home_path, '', add_query_arg( array() ) ), "https://wordpress.stackexchange.com/" );
$stripped = explode( '?', $full );
return trim( $stripped[0], "https://wordpress.stackexchange.com/" );
}
}
$rd = new RedirectDeletedTag();
add_action( 'shutdown', array( $rd, 'cacheUrls' ) );
add_action( 'after_setup_theme', array( $rd, 'redirect' ) );
Плагин доступен как Gist здесь.
* Чтобы запустить одноразовое задание, я буду использовать временную метку плюс проверку, является ли текущий пользователь администратором, также наличие кэш-файла. Если хотите, рассмотрите этот вопрос/ответы, чтобы узнать о различных подходах к одноразовым задачам в WordPress.
Ответ или решение
Решение проблемы редиректа удалённых постов в WordPress на другой сайт
Ваша задача заключается в том, чтобы настроить редирект с удалённых постов на основной сайт WordPress на новый сайт WordPress, что является важной частью для улучшения производительности и скорости загрузки вашего сайта.
Исходные данные
- У вас есть основной сайт:
http://www.example.com/
с более чем 540,000 постами. - Вы создали новый сайт:
http://www.example.com/business-consultants/
, на который перенесли 3135 постов, помеченных тегом ‘Business Consultants’. - Вам необходимо настроить 301 редирект, который будет работать даже после удаления постов с основного сайта.
Предложенное решение
Вы можете использовать плагин, который будет выполнять следующие шаги:
- Получить все посты с тегом ‘business-consultants’.
- Сохранить их в PHP-файле для последующего использования.
- Удалить эти посты с основного сайта.
- Настроить редирект для каждого из этих постов.
Важно!
Перед началом любых манипуляций обязательно сделайте полную резервную копию базы данных веб-сайта. Это поможет восстановить систему в случае непредвиденных проблем.
Код плагина
Сохраните следующий код в файле RedirectDeleted.php
и разместите его в папке плагинов вашего WordPress. После этого активируйте плагин:
<?php
/**
* Plugin Name: RedirectDeletedTag
* Plugin URI: https://wordpress.stackexchange.com/questions/136018/
*/
class RedirectDeletedTag {
// Настройте массив тегов и URL для редиректа.
protected $target_tags = array(
'business-consultants' => 'http://www.example.com/business-consultants/',
);
function cacheUrls() {
if (!is_admin() || !current_user_can('install_plugins')) return;
foreach($this->target_tags as $tag => $url) {
if ($this->shouldCache($tag)) $this->cacheTagUrls($tag);
}
}
function redirect() {
if (is_admin()) return;
$url = $this->getUrl();
if (!empty($url)) {
foreach($this->target_tags as $tag => $base) {
$this->redirectTag($tag, $url, $base);
}
}
}
protected function cacheTagUrls($tag) {
$args = array('post_type' => 'post', 'nopaging' => true, 'tag' => $tag);
$query = new WP_Query($args);
if ($query->have_posts()) {
$slugs = wp_list_pluck($query->posts, 'post_name');
$id_list = implode(',', wp_list_pluck($query->posts, 'ID'));
$cache="<?php return array(\"" . implode("\",\"", $slugs) . "\");";
if (@file_put_contents($this->getCachePath($tag), $cache) !== FALSE) {
set_transient(__CLASS__ . $tag, '1');
global $wpdb;
$wpdb->query("DELETE FROM $wpdb->posts WHERE ID IN ($id_list)");
$term = get_term_by('slug', $tag, 'post_tag');
if (!empty($term) && isset($term->term_id)) {
wp_delete_term($term->term_id, 'post_tag');
}
}
}
}
protected function redirectTag($tag, $url, $base) {
if (file_exists($this->getCachePath($tag))) {
$cached = (array) include $this->getCachePath($tag);
if (in_array($url, $cached)) {
wp_redirect(trailingslashit($base) . $url);
exit();
}
}
}
protected function shouldCache($tag = '') {
return is_admin() && current_user_can('install_plugins') && empty(get_transient(__CLASS__ . $tag)) && !file_exists($this->getCachePath($tag));
}
protected function getCachePath($tag = '') {
$upload_dir = wp_upload_dir();
return trailingslashit($upload_dir['basedir']) . 'redirect_deleted_' . $tag . '.php';
}
protected function getUrl() {
$full = trim($_SERVER['REQUEST_URI'], '/');
return trim($full, '/');
}
}
$rd = new RedirectDeletedTag();
add_action('shutdown', array($rd, 'cacheUrls'));
add_action('after_setup_theme', array($rd, 'redirect'));
Как это работает?
- Плагин проверяет наличие постов с указанным тегом и создает файл кэша с их слагами.
- При посещении удалённого поста, если в кэше есть соответствующий слаг, производится редирект на новый сайт.
Заключение
Это решение универсально и может быть адаптировано для работы с другими тегами и сайтами. Убедитесь в тестировании на локальной среде перед применением на живом сайте, чтобы избежать негативного влияния на пользователей и SEO.