Я столкнулся со странной проблемой.
Допустим, у вас есть произвольный URL-адрес глубиной три или более:
http://example.com/a/b/c
http://example.com/a/b/c/d
...
Тогда is_404()
есть true
. Все идет нормально. Но почему-то последние посты запрашиваются.
$wp_query->request
является
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
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 0, 5
Который тогда, конечно, делает have_posts()
возврат true
и так далее. Может кто-нибудь объяснить это?
Что я узнал до сих пор:
Причина того, что только начинается на трех или более уровнях, заключается в том, что до этого WP ищет сообщения и вложения, что каким-то образом приводит к некоторому другому поведению.
Кажется, что хотя WP и распознает запрос как 404, он получает самые последние сообщения. С помощью @kaiser и @GM я отследил это где-то из /wp-includes/class-wp.php:608
Ответы:
Вы можете быть удивлены, но там нет ничего странного.
Прежде всего давайте поясним, что в WordPress при посещении внешнего интерфейса вы запускаете запрос. Всегда.
Этот запрос является стандартным
WP_Query
, как и те, которые выполняются через:Разница только одна:
$args
переменные генерируются WordPress с использованиемWP::parse_request()
метода. Этот метод просто смотрит на URL и правила перезаписи и преобразует URL в массив аргументов.Но что происходит, когда этот метод не может сделать это, потому что URL недействителен? Аргументы запроса - это просто массив, подобный следующему:
(Источник здесь и здесь ).
Таким образом, этот массив передается
WP_Query
.Теперь попробуйте сделать:
Вы удивлены тем, что запрос именно тот, что в OP? Я не.
Так,
parse_request()
строит массив с ключом ошибкиWP_Query
, который просто запускает егоhandle_404()
который запускается после запроса, смотрит на'error'
параметр и устанавливаетis_404()
значение trueТак что
have_post()
иis_404()
не связаны. Проблема в том, чтоWP_Query
у системы нет системы для короткого замыкания запроса, когда что-то идет не так, поэтому, как только объект построен, передайте ему несколько аргументов, и запрос будет выполненРедактировать:
Есть 2 способа преодолеть эту проблему:
404.php
шаблон; WordPress загрузит это на 404 URL и там вам не нужно проверятьhave_posts()
Заставьте
$wp_query
быть пустым на 404, что-то вроде:источник
$wp->matched_rule
), но запрос все еще проходит через движения, потому что не обращает на это внимания.WHERE 1=0
в sql, потому что он не может остановить запрос, поэтому принудительно выполняйте запрос, который ничего не возвращает ... @Rarstis_404()
проверку.