web-dev-qa-db-de.com

Wann/warum wird '$ query-> get (' tax_query ');' leer zurück?

Zuerst der Code:

function itsme_better_editions( $query ) {
    if ( $query->is_category() && $query->is_main_query() ) {
        $query->set( 'post_type', array( 'post' ) );

        // Get current tax query
        $tax_query = $query->get( 'tax_query' );

        $tax_query['relation'] = 'OR';

        $tax_query[] = array(
            'taxonomy' => 'category',
            'field' => 'slug',
            'terms' => 'intl',
            'operator' => 'IN'
        );

        $query->set( 'tax_query', $tax_query );
    }
    return $query;
}
add_filter( 'pre_get_posts', 'itsme_better_editions' );

Es scheint mir alles in Ordnung zu sein, außer dass $query->get( 'tax_query' ); ein leeres oder kein Array zurückgibt, d. H. Die folgende Bedingung gibt true zurück:

if( !empty($tax_query) || is_array($tax_query) ) {
   // whatever
}

Dies ist das Brechen von Sachen, die ich später erkannte .

Die richtigen Beiträge werden im Archiv angezeigt, d. H. Beiträge, die entweder zur aktuellen Kategorie OR 'International (intl)' gehören, werden aufgelistet. Welches ist, was ich will.

Das Termobjekt zeigt jedoch auf die Kategorie 'intl' (dasselbe passiert auch in Tag-Archiven; anstelle des Termobjekts, das auf das aktuelle Tag verweist, zeigt es auf die Kategorie 'intl'). Wenn ich beispielsweise das Kategoriearchiv "UK (uk)" besuche, wird "International" anstelle von "UK" angezeigt.

Dies ist nur eines der Probleme, die mir bisher aufgefallen sind. Ich weiß nicht, was sonst noch kaputt ist.

Was ist los mit der Funktion?


PS: Und da $query->get( 'tax_query' ); leer oder kein Array zurückgab, musste ich es manuell wie folgt auffüllen:

/*
 * Show posts assigned to 'International (intl)' Edition
 * in all editions.
 */
function itsme_better_editions( $query ) {
    if( $query->is_category() && $query->is_main_query() ) {

        $query->set( 'post_type', array( 'post' ) );

        // NOT WORKING!!!
        //$tax_query = $query->get( 'tax_query' );

        // Equivalent of original `$tax_query` START.
        $get_original_category = get_query_var( 'category_name' );
        $original_category = get_term_by( 'slug', $get_original_category, 'category' );
        if( $original_category && !is_wp_error( $original_category ) ) {
            $itsme_original_category = $get_original_category;
        }

        $tax_query[] = array(
            'taxonomy' => 'category',
            'field' => 'slug',
            'terms' => $original_category,
            'operator' => 'IN'
        );
        // Equivalent of original `$tax_query` END.

        $tax_query['relation'] = 'OR';

        $tax_query[] = array(
            'taxonomy' => 'category',
            'field' => 'slug',
            'terms' => 'intl',
            'operator' => 'IN'
        );

        $query->set( 'tax_query', $tax_query );
    }
    return $query;
}
add_filter( 'pre_get_posts', 'itsme_better_editions' );

ODER ersetzen Sie die Abfrage einfach wie folgt:

/*
 * Show posts assigned to 'International (intl)' Edition
 * in all editions.
 */
function itsme_better_editions( $query ) {
    if( $query->is_category() && $query->is_main_query() ) {

        // Get original/actual category of the category archive
        $get_original_category = get_query_var( 'category_name' );
        $original_category = get_term_by( 'slug', $get_original_category, 'category' );
        if( $original_category && !is_wp_error( $original_category ) ) {
            $itsme_original_category = $get_original_category;
        }

        if( isset($itsme_original_category) ) {

            $query->set( 'post_type', array( 'post' ) );

            $query->set( "category_name", "{$itsme_original_category}, intl" );

        }

    }
}
add_action( 'pre_get_posts', 'itsme_better_editions' );

Das funktioniert, aber warum soll ich das so machen? Soll $tax_query = $query->get( 'tax_query' ); nicht den ursprünglichen tax_query zurückgeben?


Wie reproduziere ich das Problem?

1. Erstellen Sie zwei Kategorien: UK (uk) und International (intl). Erstellen Sie zwei Posts und weisen Sie sie nur "Großbritannien" zu. 1 nur unter 'International'.

Jetzt zeigt example.com/category/uk/ 2 Beiträge; und example.com/category/intl/ zeigt 1.

2. Fügen Sie nun die erste Funktion (den ersten Codeblock) in die functions.php Ihres Themas ein und besuchen Sie example.com/category/uk/. Sie werden sehen, dass der Kategoriename der Seite (<?php single_cat_title(); ?>) als "International" angezeigt wird. Warum? Wenn ich mich nicht irre, weil $ query-> get ('tax_query'); scheint leer zu sein, kein Array.

3. Ersetzen Sie die Funktion in functions.php durch die zweite oder dritte Funktion oben. Jetzt sollte alles so funktionieren, wie es soll.

PS: Ja, ich habe diesen Test selbst mit dem Standardthema (Twenty Thirteen) durchgeführt und er bleibt bestehen. Sie können das Problem also problemlos reproduzieren.

3
its_me

AFAIK $query->get für Hauptabfrage funktioniert nur mit öffentlichen Abfragevariablen, dh Variablen, die über URL ausgelöst werden können, aber nichts hindert den direkten Zugriff auf die Eigenschaft tax_query der Abfrage, sondern stellt fest, dass es sich um ein Objekt, eine Instanz von WP_Tax_Query und handelt Die aktuell abgefragten Taxonomieargumente befinden sich in der Eigenschaft queries dieses Objekts.

Wenn Sie auf diese Eigenschaft zugreifen, vermeiden Sie es, in Ihrer Funktion eine andere Abfrage mit get_term_by auszuführen. Als Nebeneffekt gibt single_cat_title den richtigen Titel aus:

function itsme_better_editions( $query ) {

  if ( $query->is_category() && $query->is_main_query() ) {

    $query->set( 'post_type', array( 'post' ) );

    $tax_query_obj = clone $query->tax_query;

    $tax_query_obj->queries[] = array(
      'taxonomy' => 'category',
      'field' => 'slug',
      'terms' => 'intl',
      'operator' => 'IN'
    );

    $tax_query = array('relation' => 'OR');

    foreach ( $tax_query_obj->queries as $q ) {
      $tax_query[] = $q;
    }

    $query->set('tax_query', $tax_query);
  }

}

add_action( 'pre_get_posts', 'itsme_better_editions' );

Beachten Sie, dass Sie den Filter auch für Administratorabfragen ausführen. Wenn dies nicht der Fall ist, fügen Sie && ! is_admin() in first if conditional in function hinzu.

PS: ein Tipp: Wenn Sie 'pre_get_posts' verwenden, können Sie add_action anstelle von add_filter verwenden und nichts zurückgeben, da die Abfrage als Referenz übergeben wird.

6
gmazzap

$tax_query = $query->get( 'tax_query' ); gibt den ursprünglichen tax_query zurück, wenn einer an die Abfrage übergeben wird. Zum Beispiel:

function itsme_better_editions( $query ) {
  $query->set( 'post_type', array( 'post' ) );

  // Get current tax query
  $tax_query = $query->get( 'tax_query' );
  var_dump($tax_query); die;
}
add_action( 'pre_get_posts', 'itsme_better_editions' );

$t = new WP_Query(
  array(
    'post_type' => 'post',
    'tax_query' => array(
      array(
        'taxonomy' => 'category',
        'field' => 'slug',
        'terms' => 'intl',
        'operator' => 'IN'
      )
    )
  )
);

Wenn Sie jedoch $wp_query in einem Kategoriearchiv ablegen oder einen ähnlichen Test für die Hauptabfrage ausführen, gibt es keinen tax_query, wie Sie bereits festgestellt haben. Dies liegt daran, dass für einige der Standardabfragen das Objekt WP_Querydiesen tax_query aus anderen Abfrageparametern erstellt lange nachdem pre_get_posts ausgeführt wurde . Deshalb ist $tax_query = $query->get( 'tax_query' ); leer.

2
s_ha_dum