Почему цикл не пустой на некоторых 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

kraftner
источник
Если вы не добавите код страницы, вам будет трудно помочь
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
        }
    } );
Gmazzap
источник
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