¿Cuándo / por qué '$ query-get (' tax_query ');' volver vacio?

2

Primero el código:

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' );

Todo me parece correcto, excepto que $query->get( 'tax_query' ); parece devolver vacío o no una matriz, es decir, la siguiente condición está devolviendo true :

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

Esto está rompiendo cosas, luego me di cuenta .

Las publicaciones de la derecha se muestran en el archivo, es decir, las publicaciones que pertenecen a la categoría actual O a la categoría 'Internacional (internacional)' se enumeran. Que es lo que quiero.

Pero el término objeto se apunta a la categoría 'intl' (lo mismo sucede en los archivos de etiquetas también; en lugar de que el objeto termal apunte a la etiqueta actual, apunta a la categoría 'intl'). Por ejemplo, si visito el archivo de categoría 'UK (uk)', aparece 'International' en lugar de 'UK'.

Este es solo uno de los problemas que he notado hasta ahora; No sé qué más está roto.

¿Qué tiene de malo la función?

PS: Y como $query->get( 'tax_query' ); estaba regresando vacío o no como una matriz, tuve que llenarlo manualmente así:

/*
 * 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' );

O simplemente reemplace la consulta de esta manera:

/*
 * 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' );

Esto funciona, pero ¿por qué debería hacerlo de esta manera? ¿No se supone que $tax_query = $query->get( 'tax_query' ); devuelve el tax_query original?

Cómo reproducir el problema

1. Cree dos categorías: Reino Unido (Reino Unido) e Internacional (internacional). Cree 2 publicaciones y asígnelas a 'UK' solamente; 1 solo bajo 'Internacional'.

Ahora, example.com/category/uk/ muestra 2 publicaciones; y example.com/category/intl/ muestra 1.

2. Ahora agregue la primera función (primer bloque de código) en las funciones de su tema.php, y visite example.com/category/uk/ . Verá que el nombre de la categoría de la página ( <?php single_cat_title(); ?> ) se muestra como 'Internacional'. ¿Por qué? Si no estoy equivocado, porque $ query- > get ('tax_query'); Parece que vuelve vacío, no una matriz.

3. Reemplace la función en functions.php con la segunda o tercera funciones anteriores. Ahora todo debería funcionar como se supone.

PS: Sí, hice esta prueba con el tema predeterminado (Twenty Thirteen) y persiste. Así que podrías reproducir el problema bien.

    
pregunta its_me 22.11.2013 - 04:00

2 respuestas

5

AFAIK $query->get para la consulta principal solo funciona con vars de consulta públicos, es decir, vars que pueden activarse a través de url, pero nada impide acceder directamente a la propiedad tax_query de la consulta, pero observe que es un objeto, instancia WP_Tax_Query y los actuales argumentos taxonómicos consultados están en la propiedad queries de ese objeto.

Al acceder a esa propiedad, evita ejecutar otra consulta con get_term_by dentro de tu función. Como efecto secundario, single_cat_title imprimirá el título correcto:

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' );

Tenga en cuenta que en realidad está ejecutando el filtro también en las consultas de administración, si no es lo que desea, agregue && ! is_admin() dentro de la primera función condicional de if .

PS: una sugerencia: cuando usas 'pre_get_posts' puedes usar add_action en lugar de add_filter y no devolver nada, porque la consulta se pasa como referencia.

    
respondido por el gmazzap 25.11.2013 - 14:24
1

$tax_query = $query->get( 'tax_query' ); devolverá el tax_query original si se pasa uno a la consulta. Por ejemplo:

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'
      )
    )
  )
);

Sin embargo, si vuelca $wp_query en un archivo de categoría, o ejecuta una prueba similar en la consulta principal, no hay tax_query como ya descubrió. Esto se debe a que para algunas de las consultas predeterminadas, el objeto WP_Query , construye ese tax_query a partir de otros parámetros de consulta mucho después de que pre_get_posts se ejecute . Es por eso que $tax_query = $query->get( 'tax_query' ); está vacío.

    
respondido por el s_ha_dum 29.11.2013 - 05:59

Lea otras preguntas en las etiquetas