Perché il loop non è vuoto su alcuni 404?


10

Mi sono imbattuto in uno strano problema.

Supponi di accedere a un URL casuale, con tre o più livelli di profondità:

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

Quindi lo is_404()è true. Fin qui tutto bene. Ma per qualche motivo vengono interrogati gli ultimi post.

$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

Che poi ovviamente fa have_posts()ritorno truee così via. Qualcuno può spiegare questo?

Quello che ho scoperto finora:

La ragione per cui entra in gioco solo a tre o più livelli di profondità è che prima di allora WP cerca post e allegati che in qualche modo si traducono in qualche altro comportamento.

Sembra che anche se WP riconosce la richiesta come 404 a un certo punto, recupera i post più recenti. Con l'aiuto di @kaiser e @GM ho rintracciato questo da qualche parte da /wp-includes/class-wp.php:608


Se non aggiungi il codice della pagina sarà difficile aiutarti
Tomás Cot

3
Questo non è specifico per il mio codice. Si comporta in questo modo su una nuova installazione con tutti i temi predefiniti.
Kraftner,

puoi nominare almeno un tema, nel mio tema personalizzato non funziona? stai usando parametri specifici? hai cambiato le lumache? quale versione di WP stai usando?
Tomás Cot

Davvero qualsiasi. Ma prova Twenty Eleven se vuoi.
Kraftner,

Mi dispiace per tutta la domanda, pensavo che i post fossero in mostra.
Tomás Cot

Risposte:


9

Potresti essere sorpreso, ma non c'è niente di strano lì.

Prima di tutto chiariamo che in WordPress quando si visita un URL frontend si attiva una query. Sempre.

Quella query è solo uno standard WP_Query, proprio come quelli eseguiti tramite:

$query = new WP_Query( $args );

C'è solo una differenza: le $argsvariabili sono generate da WordPress usando il WP::parse_request()metodo. Quello che fa questo metodo è solo guardare l'URL e le regole di riscrittura e convertire l'URL in una matrice di argomenti.

Ma cosa succede quando quel metodo non è in grado di farlo perché l'URL non è valido? La query args è solo una matrice come questa:

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

(Fonte qui e qui ).

In tal modo l'array viene passato a WP_Query.

Ora prova a fare:

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

Sei sorpreso che la query sia esattamente quella in OP? Non sono.

Così,

  1. parse_request() crea un array con una chiave di errore
  2. Quell'array viene passato a WP_Query, che lo esegue
  3. handle_404()che viene eseguito dopo la query, osserva il 'error'parametro e si imposta is_404()su true

Quindi, have_post()e is_404()non sono correlati. Il problema è che WP_Querynon esiste un sistema per cortocircuitare la query quando qualcosa va storto, quindi una volta che l'oggetto è stato creato, passa alcuni argomenti e la query verrà eseguita ...

Modificare:

Esistono 2 modi per superare questo problema:

  • Crea un 404.phpmodello; WordPress lo caricherà su 404 URL e lì non dovrai controllarehave_posts()
  • Forza $wp_querydi essere vuoto su 404, qualcosa del tipo:

    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
Vorrei aggiungere che la ragione per cui ciò non accade in genere è che 404 di solito è il risultato di una query . Ma in questo caso è il risultato di una regola di riscrittura senza pari ( $wp->matched_rule), ma la query sta ancora eseguendo i movimenti perché non presta attenzione a questo.
Rarst

+1. Sì, la query non lo presta attenzione e con il codice corrente non può prestare attenzione, perché non c'è modo di fermarlo. Ad esempio, quando viene richiesta una tassonomia non valida, WordPress viene impostato WHERE 1=0in sql perché non può arrestare la query, quindi forzare una query che non restituisca nulla ... @Rarst
gmazzap

Va bene ora capisco. Quindi la vera domanda che rimane è perché diavolo WP_Query assume una query predefinita per ottenere post quando non si passano argomenti ragionevoli quando semplicemente restituendo nulla avrebbe molto più senso?
Kraftner,

2
@kraftner come detto WordPress non può evitare l'esecuzione della query, e quando non ci sono argomenti resonable ci sono 2 scelte: eseguire una query che sicuramente non restituisce nulla (come quando viene richiesta una tassonomia non valida, vedere il commento sopra) o eseguire la query predefinita . Perché in questo caso WP sceglie quest'ultimo è un Q che dovrebbe essere chiesto agli sviluppatori principali :)
gmazzap

@ TomásCot Certo, ma se fallisce, vorrei che fallisse davvero e non restituisse qualcosa di totalmente indipendente. Ad ogni modo, le cose si sono chiarite ora e devo solo fare un is_404()controllo aggiuntivo .
Kraftner,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.