¿Debo usar Pre Get Posts o WP_Query

29

Tengo la siguiente consulta que llamo en mi plantilla taxonomy.php a través de query_brands_geo('dealers', 'publish', '1', $taxtype, $geo, $brands);

Esta función funciona perfectamente. Sin embargo, después de leer el códice para publicaciones de consultas, mencionó pre_get_posts como una forma preferida de alterar la consulta predeterminada. ¿Pre_get_posts sería más eficiente que mi función wp_query a continuación?

Si es así, ¿cómo construiría pre_get_posts y pasaría mi variable y consulta a continuación?

function my_custom_query($posttype, $poststatus, $paidvalue, $taxtype, $geo, $brands) {
   global $wp_query; 
   $wp_query = new WP_Query();
   $args = array( 
      'post_type' => $posttype, 
      'post_status' => array($poststatus), 
      'orderby' => 'rand', 
      'posts_per_page' => 30, 
      'meta_query' => array( 
         array( 
            'key' => 'wpcf-paid', 
            'value' => array($paidvalue), 
            'compare' => 'IN', 
            ) 
      ), 
      'tax_query' => array( 
         'relation' => 'AND', 
         array( 
            'taxonomy' => $taxtype, 
            'field' => 'slug', 
            'terms' => $geo 
         ), 
         array( 
            'taxonomy' => 'brands', 
            'field' => 'slug', 
            'terms' => $brands 
         ) 
      ) 
   ); 

   return $wp_query->query($args); 
} 
usuario1609391
fuente

Respuestas:

14

pre_get_postsejecutará la misma consulta, por lo que ambos tomarán el mismo tiempo. Pero, si utiliza la pre_get_postsacción, guardará una o más consultas SQL. En este momento, WordPress ejecuta una consulta predeterminada y luego ejecuta su consulta con esta función que reemplaza los resultados de la consulta predeterminada (resultante, la consulta predeterminada no sirve de nada). A continuación se muestra cómo se puede mover su $argsa

function custom_pre_get_posts($query, $posttype='dealers', $poststatus='publish', $paidvalue='1', $taxtype='any_default_value', $geo='any_default_value', $brands='any_default_value') {

    // filter your request here.
    if($query->is_category) {

        $args = array(
            'post_type' => $posttype,
            'post_status' => array($poststatus),
            'orderby' => 'rand',
            'posts_per_page' => 30,
            'meta_query' => array(
                array(
                    'key' => 'wpcf-paid',
                    'value' => array($paidvalue),
                    'compare' => 'IN',
                )
            ),
            'tax_query' => array(
                'relation' => 'AND',
                array(
                    'taxonomy' => $taxtype,
                    'field' => 'slug',
                    'terms' => $geo
                ),
                array(
                    'taxonomy' => 'brands',
                    'field' => 'slug',
                    'terms' => $brands
                )
            )
        );
        $query->query_vars = $args;
    }
}
add_action('pre_get_posts', 'custom_pre_get_posts');
SEÑOR
fuente
Muchas gracias por la respuesta. Es de mucha ayuda. Una pregunta rapida. Puse la función en mi archivo de función function.php. Ejecuto esta función custom_pre_get_posts ($ query) desde mi taxonomy.php. En taxonomy.php configuro las variables, $ posttype, $ post_status, $ geo, $ brands, $ taxtype y ejecuto dos bucles cambiando estas variables. ¿Hay alguna manera de pasar la variable a la función anterior desde taxonomy.php? Cuando intento custom_pre_get_posts ($ consulta, 'distribuidores', 'publicar', '1', $ taxtype, $ geo, $ brands); Me faltan argumentos de 2 a 7 para custom_pre_get_posts (). Supongo que debido a add_action ???
user1609391
1
Supongo que ha cambiado custom_pre_get_posts para aceptar los argumentos restantes. Sí, obtiene un error debido a add_action. add_action llama a esta función con un solo argumento (es decir, $ query), debe dar valores predeterminados a otros argumentos para evitar errores de argumento faltantes. like ($ posttype = null, $ poststatus = null ...) para que pueda ser llamado adecuadamente por add_action.
MR
MR Gracias por la respuesta. Leí sobre la acción de agregar y veo que debería asignar una prioridad y un número de argumentos. Así que cambié mi acción de agregar a <code> add_action ('pre_get_posts', 'custom_pre_get_posts', 10,7); </code> Luego, en mi página taxonomy.php, I <code> do_action ('pre_get_post', $ query, ' distribuidores ',' publicar ',' 1 ', $ taxtype, $ geo, $ brands); </code>. Pero sigo recibiendo el mismo error. No estaba seguro de dónde poner los valores predeterminados. Intenté google pero no pude encontrar una referencia. ¿Me puede dar un poco más de información sobre cómo manejar esto?
user1609391
Gracias por la respuesta y el ejemplo. Pero creo que podría estar tratando de usar pre_get_posts cuando debería estar haciendo una nueva consulta de WordPress. Intenté guardar una consulta, pero en mi caso podría no ser posible. La razón es que todos los argumentos que estableció en el parámetro, quería pasar a la función desde mi archivo taxonomy.php. Entonces $ paidvalue = ”1” podría ser 1 o 0 dependiendo de la condición que estoy ejecutando en taxonomy.php. Parece que pre_get_posts arriba se dispara justo cuando se carga la página, incluso si no llamo a la función en mi archivo taxonomy.php. ¿Estoy viendo esto correcto?
user1609391
3
Esta respuesta no tiene sentido ya que está escrita actualmente. Efectivamente sobrescribirá cualquier valor dentro del $wp_queryobjeto y las cosas fallarán por completo. Aparte de eso, simplemente no es cierto que pre_get_postsse ejecutará una consulta adicional ...
kaiser
10

La respuesta tardía como la respuesta más votada interrumpirá su consulta y simplemente no es cierto en algunos puntos importantes.

El principal WP_Query y sus filtros

Primero, WordPress usa internamente query_posts()(un envoltorio delgado WP_Queryque no debe usarse en temas o complementos) para hacer una WP_Query. Esto WP_Queryestá actuando como el bucle principal / consulta. Esta consulta se ejecutará a través de muchos filtros y acciones hasta que se construya la cadena de consulta SQL real. Uno de esos es pre_get_posts. Otros son posts_clauses, posts_whereetc., que también le permiten interceptar el proceso de creación de cadenas de consulta.

Una mirada en profundidad a lo que sucede dentro del núcleo

WordPress ejecuta la wp()función (in wp-includes/functions.php), que llama $wp->main()( $wpes un objeto de la clase WP, que se define en wp-includes/class-wp.php). Esto le dice a WordPress que:

  1. Analice la URL en una especificación de consulta usando WP->parse_request()- más sobre eso a continuación.
  2. Establezca todas las variables is_ que usan las etiquetas condicionales usando $wp_query->parse_query()( $wp_queryes un objeto de class WP_Query, que se define en wp-includes/query.php). Tenga en cuenta que a pesar del nombre de esta función, en este caso en WP_Query->parse_queryrealidad no hace ningún análisis por nosotros, ya que eso se hace de antemano WP->parse_request().
  3. Convierta la especificación de consulta en una consulta de base de datos MySQL y ejecute la consulta de base de datos para obtener la lista de publicaciones, en la función WP_Query-> get_posts (). Guarde las publicaciones en el objeto $ wp_query para usar en el bucle de WordPress.

Codex fuente

Conclusión

Si realmente desea modificar la consulta principal, puede usar una amplia variedad de filtros. Simplemente use $query->set( 'some_key', 'some_value' );para cambiar datos allí o use $query->get( 'some_key' );para recuperar datos para hacer verificaciones condicionales. Esto le ahorrará hacer una segunda consulta, ya que solo está alterando la consulta SQL.

Si tiene que hacer una consulta adicional , vaya con un WP_Queryobjeto. Esto agregará otra consulta a la base de datos.

Ejemplo

Como las respuestas siempre funcionan mejor con un ejemplo, aquí tienes uno realmente bueno (accesorios para Brad Touesnard), que simplemente extiende el objeto central y, por lo tanto, es bastante reutilizable (crea un complemento):

class My_Book_Query extends WP_Query
{
    function __construct( $args = array() )
    {
        // Forced/default args
        $args = array_merge( $args, array(
            'posts_per_page' => -1
        ) );

        add_filter( 'posts_fields', array( $this, 'posts_fields' ) );

        parent::__construct( $args );
    }

    public function posts_fields( $sql )
    {
        return "{$sql}, {$GLOBALS['wpdb']->terms}.name AS 'book_category'";
    }
}

Luego puede ejecutar su segunda consulta / adicional como puede ver en el siguiente ejemplo. No olvide restablecer su consulta después.

$book_query = new My_Book_Query();
if ( $book_query->have_posts() )
{
    while ( $book_query->have_posts() )
    {
        $book_query->the_post();
        # ...do stuff...
    } // endwhile;
    wp_reset_postdata();
} // endif;
emperador
fuente