Por que o loop não está vazio em alguns 404s?


10

Me deparei com uma questão estranha.

Digamos que você acesse um URL aleatório, com três ou mais níveis de profundidade:

http://example.com/a/b/c
http://example.com/a/b/c/d
...

Então is_404()é true. Por enquanto, tudo bem. Mas, por algum motivo, as últimas postagens são consultadas.

$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

O que, é claro, faz have_posts()retorno truee assim por diante. Alguém pode explicar isso?

O que eu descobri até agora:

A razão pela qual apenas entra em ação em três ou mais níveis é que, antes disso, o WP procura por postagens e anexos que de alguma forma resultam em algum outro comportamento.

Parece que, embora o WP reconheça a solicitação como 404 em um ponto, ele busca as postagens mais recentes. Com a ajuda do @kaiser e do @GM , localizei isso em algum lugar de /wp-includes/class-wp.php:608


Se você não adicionar o código da página, será difícil ajudá-lo
— Tomás Cot

3
Isso não é específico para o meu código. Comporta-se assim em uma nova instalação com todos os temas padrão.
— kraftner 12/09

você pode citar pelo menos um tema, no meu tema personalizado não está funcionando? você está usando parâmetros específicos? você mudou as lesmas? qual versão do WP você está usando?
— Tomás Cot

Realmente qualquer. Mas tente Twenty Eleven, se quiser.
— kraftner 12/09

Desculpe por toda a pergunta, achei que as postagens estavam sendo exibidas.
— Tomás Cot

Respostas:


9

Você pode se surpreender, mas não há nada de estranho lá.

Antes de tudo, vamos esclarecer que no WordPress, quando você visita um URL de front-end, aciona uma consulta. Sempre.

Essa consulta é apenas um padrão WP_Query, assim como as executadas por:

$query = new WP_Query( $args );

Há apenas uma diferença: as $argsvariáveis ​​são geradas pelo WordPress usando o WP::parse_request()método O que esse método faz é apenas olhar para o URL e as regras de reescrita e converter o URL em uma matriz de argumentos.

Mas o que acontece quando esse método não é capaz de fazer isso porque o URL não é válido? Os argumentos da consulta são apenas uma matriz como esta:

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

(Fonte aqui e aqui ).

Portanto, essa matriz é passada para WP_Query.

Agora tente fazer:

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

Você está surpreso que a consulta seja exatamente a do OP? Eu não sou.

Então,

  1. parse_request() cria uma matriz com uma chave de erro
  2. Essa matriz é passada para WP_Query, que apenas a executa
  3. handle_404()executado após a consulta, analisa o 'error'parâmetro e define is_404()como true

Então, have_post()e is_404()não estão relacionados. O problema é que WP_Querynão há um sistema que provoque um curto-circuito na consulta quando algo der errado. Assim que o objeto for criado, passe alguns argumentos para ela e a consulta será executada ...

Editar:

Existem 2 maneiras de superar esse problema:

  • Crie um 404.phpmodelo; O WordPress carregará isso em 404 URLs e você não precisará procurarhave_posts()
  • Forçar $wp_querya ficar vazio no 404, algo como:

    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
Eu acrescentaria que a razão pela qual isso não ocorre normalmente é que 404 geralmente é resultado da consulta . Mas, nesse caso, é o resultado de uma regra de reescrita inigualável ( $wp->matched_rule), mas a consulta ainda está sendo processada porque não presta atenção a isso.
— Rarst 12/09/14

+1. Sim, a consulta não presta atenção a ela e, com o código atual, ela não pode prestar atenção, porque não há como parar. Como exemplo, quando uma taxonomia não válido é consultado conjunto WordPress WHERE 1=0no SQL porque não pode parar a consulta para forçar uma consulta que retorno nada ... @Rarst
— gmazzap

Ok, agora eu entendi. Portanto, a verdadeira questão que resta é por que diabos o WP_Query assume uma consulta padrão de obtenção de postagens quando passado sem argumentos razoáveis, quando apenas retornando nada faria muito mais sentido?
— Kraftner 12/09/14

2
O @kraftner, como disse o WordPress, não pode evitar a execução da consulta, e quando não há argumentos ressonáveis, existem duas opções: executar uma consulta que com certeza não retorna nada (como quando uma taxonomia inválida é consultada, veja o comentário acima) ou executar a consulta padrão . Porque neste caso WP escolher o último é um Q que deve ser feita para devs principais :)
— gmazzap

@ TomásCot Claro, mas se falhar, quero que realmente falhe e não retorne algo totalmente não relacionado. Enfim, as coisas estão esclarecidas agora e eu só preciso fazer uma is_404()verificação adicional .
— Kraftner 12/09/14
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.