¿Debo usar Pre Get Posts o WP_Query

28

Tengo la siguiente consulta a la 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 las publicaciones de consulta, mencionó pre_get_posts como una forma preferida de alterar la consulta predeterminada. ¿Los pre_get_posts serían más eficientes que mi función wp_query a continuación?

Si es así, ¿cómo construyo los pre_get_posts y paso mi variable y la 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); 
} 
    
pregunta user1609391 18.12.2012 - 23:08

3 respuestas

14

pre_get_posts ejecutará la misma consulta, por lo que ambas tomarán el mismo tiempo. Pero, si utiliza la acción pre_get_posts , guardará una o más consultas SQL. En este momento, WordPress está ejecutando la consulta predeterminada y luego ejecuta la consulta con esta función que reemplaza los resultados de la consulta predeterminada (la consulta predeterminada resultante no tiene ninguna utilidad). A continuación se muestra cómo puede mover su $args a

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');
    
respondido por el M-R 19.12.2012 - 09:41
10

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

El main WP_Query y sus filtros

Primero, WordPress usa internamente query_posts() (una envoltura delgada alrededor de WP_Query que no debería usarse en temas o complementos) para hacer un WP_Query . Este WP_Query está actuando como el bucle / consulta principal. Esta consulta se ejecutará a través de muchos filtros y acciones hasta que se genere la cadena de consulta SQL real. Uno de ellos es pre_get_posts . Otros son posts_clauses , posts_where , etc. 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 función wp() (en wp-includes/functions.php ), que llama a $wp->main() ( $wp es 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 esto a continuación.
  2.   
  3. Establezca todas las variables is_ que son utilizadas por las etiquetas condicionales usando $wp_query->parse_query() ( $wp_query es 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 WP_Query->parse_query no realiza ningún análisis por nosotros, ya que se realiza de antemano en WP->parse_request() .
  4.   
  5. Convierta la especificación de la consulta en una consulta de la base de datos MySQL y ejecute la consulta de la 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 que se usará en el bucle de WordPress.
  6.   

Fuente Codex

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 los datos allí o use $query->get( 'some_key' ); para recuperar datos para hacer verificaciones condicionales. Esto evitará que realice una segunda consulta, ya que está modificando solo la consulta SQL.

Si tienes que hacer una consulta adicional , ve con un objeto WP_Query . Esto agregará otra consulta a la base de datos.

Ejemplo

Como las respuestas siempre funcionan mejor con un ejemplo, aquí tienes una muy buena (apoyos a 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 segundo / consulta adicional como puede ver en el siguiente ejemplo. No olvides restablecer tu 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;
    
respondido por el kaiser 10.03.2013 - 16:24
6

Por favor revise las respuestas en Cuándo usar WP_query (), query_posts () y pre_get_posts .

Es un excelente recurso si tiene alguna duda en mente.

    
respondido por el fischi 19.12.2012 - 09:51

Lea otras preguntas en las etiquetas