Dois-je utiliser Pre Get Posts ou WP_Query

29

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 messages de requête, il a mentionné pre_get_posts comme moyen préféré de modifier la requête par défaut. Les pre_get_posts seraient-ils plus efficaces que ma fonction wp_query ci-dessous?

Si oui, comment puis-je construire les pre_get_posts et passer 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); 
} 
user1609391
la source

Réponses:

14

pre_get_postsexécutera la même requête, donc les deux prendront le même temps. Mais, si vous utilisez l' pre_get_postsaction, vous enregistrerez 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 (résultat, la requête par défaut est inutile). Ci - dessous comment vous pouvez déplacer votre $argsà

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');
M
la source
Merci beaucoup pour votre réponse. C'est très utile. Une petite question. J'ai placé la fonction dans mon fichier de thème function.php. J'exécute cette fonction custom_pre_get_posts ($ query) à partir de mon taxonomy.php. Dans le fichier taxonomy.php, j'ai configuré les variables, $ posttype, $ post_status, $ geo, $ marques, $ taxtype et exécuté deux boucles en changeant ces variables. Existe-t-il un moyen de passer une variable dans la fonction ci-dessus à partir de taxonomy.php? Lorsque j'essaie custom_pre_get_posts ($ query, 'dealers', 'publish', '1', $ taxtype, $ geo, $ marques); J'obtiens l'argument manquant 2 à 7 pour custom_pre_get_posts (). Je suppose en raison de add_action ???
user1609391
1
Je suppose que vous avez modifié les custom_pre_get_posts pour accepter les arguments restants. Oui, vous obtenez une erreur en raison de add_action. add_action appelle cette fonction avec un seul argument (c'est-à-dire $ query), vous devez donner des valeurs par défaut à d'autres arguments pour éviter de manquer des erreurs d'argument. comme ($ posttype = null, $ poststatus = null ...) afin qu'il puisse être correctement appelé par add_action.
MR
M. Merci pour la réponse. J'ai lu sur ajouter une action et je vois que je devrais attribuer une priorité et un numéro d'arguments. J'ai donc changé mon action d'ajout en <code> add_action ('pre_get_posts', 'custom_pre_get_posts', 10,7); </code> Puis dans ma page taxonomy.php I <code> do_action ('pre_get_post', $ query, ' revendeurs ',' publier ',' 1 ', $ taxtype, $ geo, $ marques); </code>. Mais je reçois toujours la même erreur. Je ne savais pas où mettre les valeurs par défaut. J'ai essayé Google, mais je n'ai pas trouvé de référence. Pouvez-vous me donner un peu plus d'informations sur la façon de gérer cela?
user1609391
Merci pour la réponse et l'exemple. Mais je pense que je pourrais essayer d'utiliser pre_get_posts alors que je devrais juste faire une nouvelle requête wordpress. J'essayais d'enregistrer une requête, mais dans mon cas, cela pourrait ne pas être possible. La raison étant que tous les arguments que vous définissez dans le paramètre, je voulais passer à la fonction de mon fichier taxonomy.php. Donc $ paidvalue = ”1” peut être 1 ou 0 selon la condition que j'exécute dans taxonomy.php. Il semble que pre_get_posts ci-dessus se déclenche juste lorsque la page se charge, même si je n'appelle pas la fonction dans mon fichier taxonomy.php. Suis-je en train de voir cela correctement?
user1609391
3
Cette réponse est insensée telle qu'elle est actuellement écrite. Vous écraserez efficacement toute valeur à l'intérieur de l' $wp_queryobjet et les choses échoueront complètement. En dehors de cela, ce n'est tout simplement pas vrai qui pre_get_postsexécutera une requête supplémentaire ...
kaiser
10

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

Le WP_Query principal et ses filtres

Tout d'abord, WordPress utilise en interne query_posts()(un wrapper mince autour WP_Queryqui ne devrait pas être utilisé dans les thèmes ou les plugins) pour faire un WP_Query. Il WP_Querys'agit de la boucle / requête principale. Cette requête exécutera de nombreux filtres et actions jusqu'à ce que la chaîne de requête SQL réelle soit créée. L'un d'eux est pre_get_posts. D'autres sont posts_clauses, posts_whereetc., qui vous permettent également d'intercepter le processus de construction de la chaîne de requête.

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

WordPress exécute la wp()fonction (in wp-includes/functions.php), qui appelle $wp->main()( $wpest un objet de classe WP, qui est 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 ci-dessous.
  2. Définissez toutes les variables is_ utilisées par les balises conditionnelles à l'aide de $wp_query->parse_query()( $wp_queryest un objet de class WP_Query, qui est défini dans wp-includes/query.php). Notez que malgré le nom de cette fonction, dans ce cas, WP_Query->parse_queryne fait aucune analyse pour nous, car cela est fait au préalable par WP->parse_request().
  3. Convertissez la spécification de requête en une requête de base de données MySQL et exécutez la requête de base de données 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.

Codex source

Conclusion

Si vous souhaitez vraiment modifier la requête principale, vous pouvez utiliser une grande variété de filtres. Utilisez-le simplement $query->set( 'some_key', 'some_value' );pour y modifier des données ou utilisez-le $query->get( 'some_key' );pour récupérer des données afin d'effectuer des vérifications conditionnelles. Cela vous évitera de faire une deuxième requête, car vous ne modifiez que la requête SQL.

Si vous devez faire une requête supplémentaire , optez pour un WP_Queryobjet. Cela ajoutera une autre requête à la base de données.

Exemple

Comme les réponses fonctionnent toujours mieux avec un exemple, vous en avez ici un très joli (accessoires à Brad Touesnard), qui étend simplement l'objet principal et est donc assez réutilisable (faites-en 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 deuxième 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;
kaiser
la source