Баг: 404 статус ответа для пагинации
Суть проблемы в том, что основной запрос WP (который не нужен в этом случае) все же делается и мешает нормальной работе карты сайта.
Баг проверен на WP 5.6.1
Тикет по этому багу: https://core.trac.wordpress.org/ticket/51912
Смоделируем проблему
Для этого создадим 5 записей типа page
, 1 запись типа post и ограничим кол-во ссылок на странице карты до 1, таким кодом:
add_filter( 'wp_sitemaps_max_urls', function(){ return 1; } );
Теперь зайдя на страницу карты сайта /wp-sitemap-posts-page-4.xml
мы увидим 4 страницу пагинации карты сайта, все вроде бы ОК, но если посмотреть на статус ответа, то мы увидим 404 (такой статус не подходит для поисковиков).
Почему так происходит
Когда мы заходим на страницу /wp-sitemap-posts-page-4.xml
сначала делается основной WP запрос WP::main():
public function main( $query_args = '' ) { $this->init(); $this->parse_request( $query_args ); $this->send_headers(); $this->query_posts(); //> — делает запрос $this->handle_404(); //> — проверяет есть ли данные, если нет ставит статус 404 $this->register_globals(); do_action_ref_array( 'wp', array( &$this ) ); }
В этом случае основной запрос выглядит так:
SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 30, 10
Как мы видим этот запрос вообще не связан с картой сайта и текущими параметрами запроса. Этот запрос вернет пустой результат, потому что записей типа post
у нас столько нет.
Далее сработает метод WP::handle_404() который выставит status_header( 404 );
потому что $wp_query->posts = array()
- запрос не получил никаких данных.
Далее срабатывает хук template_redirect на котором запускается вся логика карты сайта. Но 404 статус уже установлен!
Решение (в виде костыля)
Вариант 3:
// Fix for sitemaps pagination bug. Additionally improve performance a little. // @see https://core.trac.wordpress.org/ticket/51912 // TODO: check necessity and maybe delete this code add_action( 'parse_request', 'fix_sitemaps_pagination_wp_bug' ); function fix_sitemaps_pagination_wp_bug( $wp ){ if( empty( $wp->query_vars['sitemap'] ) && empty( $wp->query_vars['sitemap-stylesheet'] ) ) return; $GLOBALS['wp_query']->query_vars = $wp->query_vars; wp_sitemaps_get_server()->render_sitemaps(); }
Вариант 2:
// Fix sitemaps pagination bug. Additionally improve performance a little. // @see https://core.trac.wordpress.org/ticket/51912 // TODO: check necessity and maybe delete add_action( 'parse_query', 'fix_sitemaps_pagination_wp_bug' ); function fix_sitemaps_pagination_wp_bug( $wp_query ){ // change render_sitemaps() call to run it before main query but after query vars are set. if( isset( $wp_query->query['sitemap'] ) && $wp_query->is_main_query() && remove_action( 'template_redirect', [ wp_sitemaps_get_server(), 'render_sitemaps' ] ) ){ wp_sitemaps_get_server()->render_sitemaps(); } }
Вариант 1:
// Fix for sitemaps pagination bug. Additionally improve performance a little. // @see https://core.trac.wordpress.org/ticket/51912 // TODO: check necessity and maybe delete add_filter( 'posts_request', 'fix_sitemaps_pagination_wp_bug', 10, 2 ); function fix_sitemaps_pagination_wp_bug( $request, $wp_query ){ global $wpdb; if( isset( $wp_query->query['sitemap'] ) && $wp_query->is_main_query() ){ return "SELECT * FROM $wpdb->posts LIMIT 1"; } return $request; }