Как сделать перенаправление со страницы 404 по ее же шаблону?

ВОПРОС

Итак, сейчас я работаю с газетным сайтом. Этот веб-сайт существует уже более 10 лет. За это время на нем накопилось более 150 тысяч различных статей, которые еще читают пользователи. Этот ресурс прошел через 3 разных CMS. У каждого движка была своя структура ссылок и при каждом изменении они неправильно перенаправлялись. Поэтому, с точки зрения SEO, все архивы теперь потеряны.
Почти 90% контента веб-сайта уже не отображается, поэтому я не хочу, чтобы посетителю просто отображалась ошибка 404. Я хочу сделать так, чтобы URL-адрес преобразовывался в поисковый запрос и сайт делал попытку найти страницы по этому запросу. Если все пройдет гладко, то пользователь получит нужную страницу. Если нет – отобразится 404.
Также я немного поразмыслил над другим подходом. Можно дословно сохранить URL и отправить статус 404. Но шаблон 404 можно взять для того, чтобы отобразить поисковый запрос. Это имеет некоторое преимущество, если нашлись совпадения по запросу. Если совпадения есть, то можно принять решение о редиректе 301. В принципе, это должно работать нормально, но есть одна проблема – на моей странице 404 недоступна разбивка.
В целом, я думаю, что проблему можно решить одним из двух способов. Первый – каким-то образом заставить работать нумерацию страниц в шаблоне 404. Второй – использовать шаблон поиска. Но это уже немного сложнее. Можно удалить “searh” и подключить правила перезаписи при помощи $wp_rewrite->search_base=”;. В теории это должно превращать любой ULR в поисковый запрос. Но здесь есть одна огромная проблема – он не работает с тегами и категориями.
Я не пробовал самостоятельно это провернуть, так как даже не знаю, с чего можно начать. Также по этому вопросу очень мало документации. Надеюсь, вы поможете мне.

ОТВЕТ

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

add_filter(‘template_include’, function($template) {
if(!is_404()) {
return $template;
}
$search_query = new WP_Query(array(‘s’ => get_query_var(‘name’)));
if($search_query->have_posts()) {
// Replace the main query with the search query
global $wp_query;
$wp_query = $search_query;
// Change the response code
status_header(200);
// Use the search template
return get_search_template();
}
return $template;
});

К слову, если все работает нормально, то основной запрос лучше изменять с помощью фильтра pre_get_posts. Если поиск возвращает результаты, то для редиректа с 404 на 200 я пользуюсь status_header. В принципе, если тебе просто нужно дать пользователям контент по их запросу, то код не имеет большого значения.
Также если ты хочешь использовать только первый результат поиска, то тот код, который я привел выше, можно немного изменить:

if($search_query->have_posts()) {
$url = get_permalink( $search_query->posts[0]->ID );
wp_redirect($url);
exit;
}