Was ist die korrekte Methode zum Bestimmen von ‘is_front_page’ bei der Verwendung von Filtern wie ‘pre_get_posts’ und ‘posts_where’?

Auf meiner Website sollten mehrere Filter angewendet werden, wenn der Benutzer die statische Homepage anzeigt. is_front_page() meinem Verständnis sollte is_front_page() feststellen, ob dies tatsächlich der Fall ist.

Immer wenn ich die function verwende, finde ich manchmal, dass sie true zurückgibt (zB posts_orderby ), aber meistens gibt sie false (zB pre_get_posts , posts_fields , posts_join und posts_where ). Ungeachtet des Ergebnisses erhalte ich immer die folgende Nachricht:

Versuch, die Eigenschaft von Nicht-Objekt in {my_path} \ wp-includes \ query.php in Zeile 4373 zu erhalten

Die Methode mit der beanstandeten Zeile lautet WP_Query::is_front_page()

 public function is_front_page() { // most likely case if ( 'posts' == get_option( 'show_on_front') && $this->is_home() ) return true; /** The offending line */ elseif ( 'page' == get_option( 'show_on_front') && get_option( 'page_on_front' ) && $this->is_page( get_option( 'page_on_front' ) ) ) return true; else return false; } 

Um dieses Problem zu bekämpfen, habe ich meine eigene function geschaffen, wie unten, aber es scheint “schmutzig” zu sein, dies zu tun. Meine Frage ist also – gibt es einen besseren Weg, dies zu tun?

 function fgw_is_front_page($q){ if(!is_a($q, 'WP_Query')) return false; return (get_option('show_on_front') == 'page' && get_option('page_on_front') && $q->get('page_id') == get_option('page_on_front')); } 

Bearbeiten

Nach weiteren Untersuchungen scheint es, dass die problematische Linie tatsächlich 4369 ist (wp-includes / querey.php) – $page_obj = $this->get_queried_object();

$page_obj wird als null , was bedeutet, dass die Überprüfung auf $q->is_front_page() fehlschlägt. Dies scheint falsch zu sein, und wenn niemand erklären kann, wie dies in irgendeiner Weise zu erwarten ist, werde ich mir ein Ticket auf Trac ansehen.


Aktualisieren

Ich habe jetzt die obige function geändert. Die Verwendung des zweiten Arguments, das an alle von mir verwendeten Filter übergeben wurde (die WP_Query-Instanz), wie von @birgire erwähnt , hat es mir ermöglicht, das Globale zu beseitigen .

Wenn ich jedoch das folgende Beispiel nehme, erhalte ich immer noch die zuvor erwähnte Notiz (und das Ergebnis von false ), wenn $q->is_front_page() überprüfe –

 add_filter('posts_fields','fgw_index_posts_fields', 10, 2); function fgw_index_posts_fields($fields, $q){ global $wpdb; if(!is_admin() && is_main_query() && (is_home() || $q->is_front_page($q))) $fields.= $wpdb->prepare(', %1$s.name as category_name', $wpdb->terms); return $fields; } 

Das Ersetzen von $q->is_front_page() mit fgw_is_front_page($q) funktioniert, aber es fühlt sich wieder dreckig an, eine benutzerdefinierte Lösung verwenden zu müssen, wenn es eine fgw_is_front_page($q) gibt, die bereits existiert.

Solutions Collecting From Web of "Was ist die korrekte Methode zum Bestimmen von ‘is_front_page’ bei der Verwendung von Filtern wie ‘pre_get_posts’ und ‘posts_where’?"

In Bezug auf die posts_orderby , posts_where , posts_join und posts_clauses ist das aktuelle \WP_Query Objekt über das zweite Eingabeargument verfügbar.

Dies sind die relevanten Teile aus der class \WP_Query :

 $orderby = apply_filters_ref_array( 'posts_orderby', array( $orderby, &$this ) ); $where = apply_filters_ref_array( 'posts_where', array( $where, &$this ) ); $join = apply_filters_ref_array( 'posts_join', array( $join, &$this ) ); $clauses = (array) apply_filters_ref_array( 'posts_clauses', array( compact( $pieces ), &$this ) ); 

alles mit der apply_filters_ref_array function und &$this ist die aktuelle \WP_Query Instanz. Der Codex sagt Folgendes über diese function:

Diese function ist identisch mit apply_filters , aber die Argumente, die an die functionen übergeben werden, die an $ tag apply_filters , werden unter Verwendung eines Arrays geliefert.

Sie können auf das zweite Argument zugreifen, zum Beispiel:

 add_filter( 'posts_where', function( $where, \WP_Query $q ) { if( $q->is_front_page() ) < -- This method won't work here with a static front-page!!! { // ... } }, 10, 2 ); 

Sie müssen sich also nicht auf das globale $wp_query Objekt verlassen.

Nachdem wir dies in WP_Query , haben wir herausgefunden, warum der Aufruf der Methode is_front_page() in diesen Filterrückrufen nicht funktioniert. Das Problem liegt in der is_page() -Methode, die versucht, die get_queried_object() -Methode zu verwenden, die immer noch kein Objekt get_queried_object() .

Die is_home() -Methode funktioniert dagegen und ruft die is_page() -Methode nicht auf.

Aktualisieren:

Es scheint mindestens zwei Trac-Tickets zu geben, # 27015 und # 21790 , die sich auf dieses Problem beziehen.

In # 27015 gibt es einen vorgeschlagenen Patch von @mattonomics, der das queried_object Objekt innerhalb der parse_query() -Methode modifiziert.

Warum also nicht in unserem Fall diese Änderungen ausprobieren, sondern stattdessen den parse_query Hook:

 /** * A workaround for the is_front_page() check inside pre_get_posts and later hooks. * * Based on the patch from @mattonomics in #27015 * * @see http://wordpress.stackexchange.com/a/188320/26350 */ add_action( 'parse_query', function( $q ) { if( is_null( $q->queried_object ) && $q->get( 'page_id' ) ) { $q->queried_object = get_post( $q->get( 'page_id' ) ); $q->queried_object_id = (int) $q->get( 'page_id' ); } } ); 

Wir sollten von diesem Patch aus weitere Änderungen hinzufügen können.