Баг: 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; }