Почему цикл не пустой на некоторых 404?


10

Я столкнулся со странной проблемой.

Допустим, у вас есть произвольный 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


Если вы не добавите код страницы, вам будет трудно помочь
— Tomás Cot

3
Это не относится к моему коду. Так же ведет себя при новой установке со всеми стандартными темами.
— kraftner,

Вы можете назвать хотя бы одну тему, в моей пользовательской теме не работает? вы используете конкретные параметры? ты сменил слизняков? какую версию WP вы используете?
— Tomás Cot

Действительно любой. Но попробуйте Twenty Eleven, если хотите.
— kraftner

Извините за весь вопрос, я думал, что сообщения показывали.
— Tomás Cot

Ответы:


9

Вы можете быть удивлены, но там нет ничего странного.

Прежде всего давайте поясним, что в WordPress при посещении внешнего интерфейса вы запускаете запрос. Всегда.

Этот запрос является стандартным WP_Query, как и те, которые выполняются через:

$query = new WP_Query( $args );

Разница только одна: $argsпеременные генерируются WordPress с использованием WP::parse_request()метода. Этот метод просто смотрит на URL и правила перезаписи и преобразует URL в массив аргументов.

Но что происходит, когда этот метод не может сделать это, потому что URL недействителен? Аргументы запроса - это просто массив, подобный следующему:

array( 'error' => '404' );

(Источник здесь и здесь ).

Таким образом, этот массив передается WP_Query.

Теперь попробуйте сделать:

$query = new WP_Query( array( 'error' => '404' ) );
var_dump( $query->request );

Вы удивлены тем, что запрос именно тот, что в OP? Я не.

Так,

  1. parse_request() строит массив с ключом ошибки
  2. Этот массив передается WP_Query, который просто запускает его
  3. handle_404()который запускается после запроса, смотрит на 'error'параметр и устанавливает is_404()значение true

Так что have_post()и is_404()не связаны. Проблема в том, что WP_Queryу системы нет системы для короткого замыкания запроса, когда что-то идет не так, поэтому, как только объект построен, передайте ему несколько аргументов, и запрос будет выполнен

Редактировать:

Есть 2 способа преодолеть эту проблему:

  • Создать 404.phpшаблон; WordPress загрузит это на 404 URL и там вам не нужно проверятьhave_posts()
  • Заставьте $wp_queryбыть пустым на 404, что-то вроде:

    add_action( 'wp', function() {
        global $wp_query;
        if ( $wp_query->is_404() ) {
            $wp_query->init();
            $wp_query->is_404 = true; // init() reset 404 too
        }
    } );

4
Я бы добавил, что причина, по которой этого не происходит, обычно заключается в том, что 404 обычно является результатом запроса . Но в этом случае это результат несоответствующего правила перезаписи ( $wp->matched_rule), но запрос все еще проходит через движения, потому что не обращает на это внимания.
— Первый

+1. Да, запрос не обращает на это внимания, и в текущем коде он не может обратить на это внимание, потому что нет способа остановить его. Например, когда запрашиваемая недействительная таксономия запрашивается в WordPress, установленном WHERE 1=0в sql, потому что он не может остановить запрос, поэтому принудительно выполняйте запрос, который ничего не возвращает ... @Rarst
— gmazzap

Хорошо, теперь я понял. Таким образом, реальный вопрос, который остается, заключается в том, почему, черт возьми, WP_Query принимает заданный по умолчанию запрос на получение сообщений, когда не передано никаких разумных аргументов, когда просто ничего не возвращается, что будет иметь смысл?
— kraftner

2
@kraftner, как сказал WordPress, не может избежать выполнения запроса, и когда нет резонируемых аргументов, есть два варианта: выполнить запрос, который точно ничего не даст (например, когда запрашивается недействительная таксономия, см. комментарий выше) или выполнить запрос по умолчанию , Почему в этом случае WP выбирает последний - Q, который следует задать основным разработчикам :)
— gmazzap

@ TomásCot Конечно, но если это не удастся, я бы хотел, чтобы это действительно не сработало и не возвращало что-то совершенно не связанное. В любом случае, сейчас все прояснилось, и мне просто нужно сделать дополнительную is_404()проверку.
— kraftner
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.