Dois-je utiliser Pre Get Posts ou WP_Query

28

J'ai la requête suivante que j'appelle dans mon modèle taxonomy.php via query_brands_geo('dealers', 'publish', '1', $taxtype, $geo, $brands);

Cette fonction fonctionne parfaitement. Cependant, après avoir lu le codex pour les publications de requête, il a mentionné pré_get_posts comme moyen privilégié de modifier la requête par défaut. Les pre_get_posts seraient-ils plus efficaces que ma fonction wp_query ci-dessous?

Si tel est le cas, comment pourrais-je construire le pre_get_posts et transmettre ma variable et ma requête ci-dessous?

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); 
} 
    
posée user1609391 18.12.2012 - 23:08

3 réponses

14

pre_get_posts exécutera la même requête, donc les deux prendront le même temps. Toutefois, si vous utilisez pre_get_posts action, vous enregistrez une ou plusieurs requêtes SQL. À l'heure actuelle, WordPress exécute la requête par défaut, puis vous exécutez votre requête avec cette fonction qui remplace les résultats de la requête par défaut (la requête par défaut résultante est donc inutile). Vous trouverez ci-dessous comment déplacer votre $args vers

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');
    
réponse donnée M-R 19.12.2012 - 09:41
10

Une réponse tardive, car la réponse la plus votée cassera votre requête et n'est tout simplement pas vraie sur certains points principaux.

Le principal WP_Query et ses filtres

Tout d'abord, WordPress utilise en interne query_posts() (une enveloppe fine autour de WP_Query qui ne doit pas être utilisée dans des thèmes ou des plugins) pour effectuer un WP_Query . Ce WP_Query agit comme la boucle / requête principale. Cette requête exécute de nombreux filtres et actions jusqu'à ce que la chaîne de requête SQL réelle soit générée. L'un d'eux est pre_get_posts . Les autres sont posts_clauses , posts_where , etc. qui permettent également de vous permettre d'intercepter le processus de création d'une chaîne de requête.

Un regard en profondeur sur ce qui se passe à l'intérieur du noyau

  

WordPress exécute la fonction wp() (dans wp-includes/functions.php ), qui appelle $wp->main() ( $wp est un objet de la classe WP, défini dans wp-includes/class-wp.php ). Cela indique à WordPress de:

     
  1. Analyser l'URL dans une spécification de requête en utilisant WP->parse_request() - plus d'informations sur la base ci-dessous.
  2.   
  3. Définissez toutes les variables is_ utilisées par les balises conditionnelles à l'aide de $wp_query->parse_query() ( $wp_query est un objet de class WP_Query , défini dans wp-includes/query.php ). Notez que malgré le nom de cette fonction, dans ce cas, WP_Query->parse_query n'effectue aucune analyse syntaxique pour nous, car cela est fait d'avance par WP->parse_request() .
  4.   
  5. Convertissez la spécification de la requête en requête de base de données MySQL et exécutez la requête pour obtenir la liste des publications, dans la fonction WP_Query- > get_posts (). Enregistrez les publications dans l’objet $ wp_query à utiliser dans la boucle WordPress.
  6.   

Source Codex

Conclusion

Si vous voulez vraiment modifier la requête principale, vous pouvez utiliser une grande variété de filtres. Utilisez simplement $query->set( 'some_key', 'some_value' ); pour modifier des données ou utilisez $query->get( 'some_key' ); pour récupérer des données afin d'effectuer des contrôles conditionnels. Cela vous évitera de faire une seconde requête, car vous ne modifiez que la requête SQL.

Si vous devez effectuer une requête supplémentaire , utilisez un objet WP_Query . Cela ajoutera une autre requête à la base de données.

Exemple

Comme les réponses donnent toujours de meilleurs résultats avec un exemple, vous en avez un très beau (accessoire de Brad Touesnard), qui étend simplement l'objet principal et qui est donc plutôt réutilisable (en faire un plugin):

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'";
    }
}

Vous pouvez ensuite exécuter votre seconde / requête supplémentaire, comme vous pouvez le voir dans l'exemple suivant. N'oubliez pas de réinitialiser votre requête par la suite.

$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;
    
réponse donnée kaiser 10.03.2013 - 16:24
6

Veuillez consulter les réponses sur Quand utiliser WP_query (), query_posts () et pre_get_posts .

C’est une excellente ressource si vous avez des doutes.

    
réponse donnée fischi 19.12.2012 - 09:51

Lire d'autres questions sur les étiquettes