it-swarm.com.de

Absichtlich max_num_pages in der Hauptabfrage überschreiten, ohne 404 zu erhalten?

In author.php habe ich zwei Schleifen: die Standardschleife main loop , die alle Beiträge dieses Autors abruft, und eine andere benutzerdefinierte Schleife WP_Query mit dem Namen $secondloop. Bei beiden Abfragen ist posts_per_page auf 3 gesetzt. Jetzt möchte ich beide Abfrageergebnisse paginieren .

Dafür habe ich ein Argument zu $secondloop = new WP_Query($args) hinzugefügt:

"paged" => (get_query_var('paged')) ? get_query_var('paged') : 1;

(Lesen Sie: Setzen Sie die Seite dieser Abfrage auf dieselbe Seite wie die der Hauptabfrage ).

DAS PROBLEM:

  • Wenn die Hauptschleife mir 5 Posts gibt und mein $secondloop mir 2 gibt, dann funktioniert das Aufrufen von Seite 2 problemlos. Es zeigt mir die verbleibenden 2 Posts aus der Hauptschleife und keine aus meinem $secondloop (da es nicht in while ($secondloop->have_posts()) geht).

  • ABERWenn die Hauptschleife 2 Posts hat und $secondloop 5 Posts hat, dann ruft Seite 2 auf und führt zu 404 :( Ich möchte offensichtlich stattdessen die restlichen 2 Posts von $secondloop .

Das Ändern von Elementen in der Vorlage author.php hilft nicht weiter, da anscheinend kein PHP Code mehr ausgeführt wird, sobald WordPress feststellt, dass max_num_pages aus der Hauptschleife überschritten wurde .

Wie kann ich dieses Verhalten "überschreiben"?


DER CODE:

author.php (nur das nützliche Bit)

<?php if (have_posts()) { ?>
    <div class="row archive-grid">
        <?php while (have_posts()) : the_post();
            include(locate_template('parts/loop-archive-grid.php'));
            endwhile; ?>
    </div>
<?php }

$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$secondloop = new WP_Query(array(
    "post_type"      => "musikalbum",
    "posts_per_page" => 3,
    "author_name"    => get_query_var('author_name'),
    "paged"          => $paged
));

if ($secondloop->have_posts()) { ?>
    <div class="row archive-grid">
        <?php while ($secondloop->have_posts()) : $secondloop->the_post();
            get_template_part( 'parts/loop', 'album-grid' );
        endwhile; ?>
    </div>
    <?php author_page_navi( $loop );
} else {
    joints_page_navi();
} ?>

posts_per_page für meine Hauptabfrage in meiner functions.php einstellen

function my_post_queries( $query ) {
  if (!is_admin() && $query->is_main_query()){
    if (is_author()){
      $query->set('posts_per_page', 3);
    } else {
      $query->set('posts_per_page', 9);
    }
  }
}
add_action( 'pre_get_posts', 'my_post_queries' );

EDIT: ATTEMPT 1

Milo wies mich auf eine Antwort hin, die vorschlug, dies zu meiner functions.php hinzuzufügen:

function my_404_override() {
  global $wp_query;

  if (is_author()) {
    status_header( 200 );
    $wp_query->is_404 = false;
  }
}
add_filter('template_redirect', 'my_404_override');

Aber es zeigt mir immer noch einen 404-Fehler. Wenn ich die if-Klausel entferne, führt sie mich zur index.php, die nicht genau das ist, was ich beabsichtigt habe. Also brauche ich die if-Klausel ... aber WordPress scheint es noch nicht zu wissen!

Das direkte Einfügen des Codes in die Vorlage hat ebenfalls nicht funktioniert, auch wenn es nur diese drei Zeilen vor get_header(); sind:

global $wp_query;
status_header( 200 );
$wp_query->is_404 = false;

EDIT: ATTEMPT 2

Ich habe template_redirect über Bord geworfen, weil ich mich in pre_get_posts eingebunden habe:

function my_post_queries( $query ) {
  if (!is_admin() && $query->is_main_query()){
    if (is_author()){
      $query->set('posts_per_page', 3);
      // NEW CODE:
      $paged = (get_query_var('paged')) ? intval(get_query_var('paged')) : 1;
      global $original_page_request; // saves the original value of $paged because I'm about to alter it!
      if ($paged > $query->max_num_pages) {
        $query->set('paged', $query->max_num_pages);
        $original_page_request = $paged;
    } else {
      $query->set('posts_per_page', 9);
    }
 }
}
add_action( 'pre_get_posts', 'my_post_queries' );

Die Idee war, paged für die Hauptabfrage manuell zurückzusetzen, wenn sie max_num_pages überschreitet, und die "aktuelle Seite" in global $original_page_request zu speichern, damit mein $secondloop den Parameter paged auf setzt. Leider funktioniert es nicht. Ich war so froh, keine 404 mehr zu sehen, aber jetzt setzt sie die Hauptabfrage Seite automatisch auf 0. Warum 0 ?!

Weil in pre_get_posts Code ausgeführt wird, bevor WordPress seine Beiträge erhalten hat. Es gibt Zugriff auf $query, aber dies dient nur zum Festlegen von Abfragevariablen. Es werden keine Posts abgerufen und daher kann kein max_num_pages berechnet werden.

Das heißt, ich habe keine Ahnung, wann ich max_num_pages überschreiten werde.

Ich habe dann den neuen Code von my_post_queries( $query ) in eine andere Funktion kopiert, die sich in wp einhakt. Dort ist max_num_pages eine gültige Nummer und is_author () ist ebenfalls korrekt. Sobald ich die Anzahl der Beiträge überschreite, noch kein Glück. 404. Ich könnte $wp_query->is_404 = false setzen, aber das bringt mich wieder zum Index zurück.

2

Bei jedem Seitenaufruf führt WordPress diese Funktionen in der jeweiligen Reihenfolge aus:

init();
parse_request($query_args);
send_headers();
query_posts();
handle_404();
register_globals();

wo die Hauptabfrage nach query_posts() beendet ist. Beachten Sie, dass WordPress zu diesem Zeitpunkt die Vorlage UND alle Abfragevariablen kennt wie max_num_pages.

In handle_404() kehrt die Funktion zurück, wenn die main query Beiträge enthält, und WordPress lädt die Vorlage weiter. Anderenfalls wird ein HTTP-Status 404 gesendet und stattdessen die Vorlage 404 geladen.

Seit WordPress 4.5 gibt es einen Filter-Hook namens pre_handle_404. Wenn es auf true gesetzt ist, gibt handle_404() zurück (unabhängig davon, ob die Hauptabfrage Beiträge enthält) und die Vorlage wird weiterhin geladen.

Also nach einem viel Herumspielen klappt das endlich. Fügen Sie dies zu Ihrer functions.php hinzu:

function ignore_404_past_max_page($bool = false, $query) {
  $paged = (get_query_var('paged')) ? intval(get_query_var('paged')) : 1;
  if (is_author() && ($paged > $query->max_num_pages))
    $bool = true;
  return $bool;
}
add_filter( 'pre_handle_404', 'ignore_404_past_max_page', 10, 2);

Das ist es! Keine Bearbeitung vorhandener Funktionen, bereinigen und genau das tun, was Sie möchten: WP kann nicht ausgeführt werden. Stellen Sie einfach sicher, dass Sie WordPress auf Version 4.5 (und höher) aktualisieren!

Ein unerwünschter Nebeneffekt kann sein, dass Sie jetzt bis zum PHP_INT_MAX paginieren und leere Seiten abrufen können (es sei denn, Sie fügen zum Beispiel einige get_the_author_meta() und get_wp_user_avatar() hinzu). Sie könnten sich wahrscheinlich die maximale Seitenzahl für jeden Autor in der Datenbank merken, diese dann abfragen und mit $paged vergleichen, um $bool in der obigen Funktion auf false zu setzen. Aber ich bin wirklich glücklich darüber, wie es jetzt funktioniert.

3