it-swarm.com.de

Warum ist die Schleife bei manchen 404 nicht leer?

Ich bin auf ein seltsames Problem gestoßen.

Angenommen, Sie greifen auf eine zufällige URL zu, die mindestens drei Ebenen tief ist:

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

Dann ist is_404()true. So weit, ist es gut. Aber aus irgendeinem Grund werden die letzten Beiträge abgefragt.

$wp_query->request

ist

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

Was dann natürlich dazu führt, dass have_posts()true zurückgibt und so weiter. Kann das jemand erklären?

Was ich bisher herausgefunden habe:

Der Grund, warum nur in drei oder mehr Ebenen eintritt, ist, dass WP vorher nach Posts und Anhängen sucht, die irgendwie zu einem anderen Verhalten führen.

Es scheint, dass WP die Anfrage an einem Punkt als 404 erkennt und dann die neuesten Posts abruft. Mit der Hilfe von @kaiser und @ G.M. Ich habe das irgendwo ausfindig gemacht von /wp-includes/class-wp.php:608

10
kraftner

Sie werden vielleicht überrascht sein, aber es gibt dort nichts Seltsames.

Lassen Sie uns zunächst klären, dass Sie in WordPress beim Aufrufen einer Frontend-URL eine Abfrage auslösen. Immer.

Diese Abfrage ist nur ein Standard-WP_Query, genau wie die, die ausgeführt werden über:

$query = new WP_Query( $args );

Es gibt nur einen Unterschied: Die $args-Variablen werden von WordPress mit der WP::parse_request() -Methode generiert. Diese Methode überprüft lediglich die URL und die Umschreiberegeln und konvertiert die URL in ein Array von Argumenten.

Aber was passiert, wenn diese Methode dies nicht kann, weil die URL ungültig ist? Die Abfrage Argumente ist nur ein Array wie folgt:

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

(Quelle hier und hier ).

Das Array wird also an WP_Query übergeben.

Versuchen Sie nun Folgendes:

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

Sind Sie überrascht, dass die Abfrage genau der in OP ist? Ich bin nicht.

So,

  1. parse_request() erstellt ein Array mit einem Fehlerschlüssel
  2. Dieses Array wird an WP_Query übergeben, das es nur ausführt
  3. handle_404(), die nach der Abfrage ausführt, den Parameter 'error' überprüft und is_404() auf true setzt

have_post() und is_404() hängen also nicht zusammen. Das Problem ist, dass WP_Query kein System hat, das die Abfrage kurzschließt, wenn etwas schief geht. Übergeben Sie also nach dem Erstellen des Objekts einige Argumente, und die Abfrage wird ausgeführt ...

Bearbeiten:

Es gibt zwei Möglichkeiten, um dieses Problem zu lösen:

  • Erstellen Sie eine 404.php Vorlage; WordPress lädt das auf 404 URLs und dort müssen Sie nicht nach have_posts() suchen
  • Erzwinge, dass $wp_query auf 404 leer ist, so etwas wie:

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