Quand utiliser WP_Query vs query_posts () vs get_posts ()?

Réponses:

667
  • query_posts()est trop simpliste et une façon problématique de modifier la requête principale d’une page en la remplaçant par une nouvelle instance de la requête. Il est inefficace (ré-exécute les requêtes SQL) et échouera carrément dans certaines circonstances (particulièrement lorsqu'il s'agit de pagination de messages). Tout code WP moderne devrait utiliser des méthodes plus fiables, comme l’utilisation du pre_get_postscrochet, à cette fin. TL; DR n'utilise jamais query_posts () .

  • get_posts() son utilisation est très similaire et accepte les mêmes arguments (avec quelques nuances, comme des valeurs par défaut différentes), mais renvoie un tableau de publications, ne modifie pas les variables globales et peut être utilisée n'importe où.

  • WP_Queryest la classe qui alimente les deux dans les coulisses, mais vous pouvez également créer et travailler avec votre propre instance. Un peu plus complexe, moins de restrictions, également sûr à utiliser n'importe où.

Rarst
la source
8
@jjeaton query_posts()est une fonction d'emballage minuscule WP_Query, sa seule chose supplémentaire à faire (comme le montre l'organigramme) est de remplacer tout le monde$wp_query
Rarst
7
@jjeaton Remplacer query_posts()par WP_Queryne fera aucune différence en termes de performances, la requête de la page d'origine sera toujours exécutée car elle fait partie de la charge principale. Ces requêtes seront exécutées même si votre fichier de modèle n'a aucune boucle.
Rarst
116
Je ne peux pas me débarrasser du sentiment qu'il s'agit de la publication la plus géniale et la plus votée de WPSE. Devrait être dans le Codex aussi bien.
Kaiser
8
J'ajouterai simplement ma description la plus claire du problème de "performances de query_posts ()": l'utilisation de query_posts () ou de WP_Query dans un fichier modèle aura le même coût de performance: la requête que vous venez d'exécuter. Le problème abordé dans l'article du codex est que si vous souhaitez réellement remplacer la requête, vous devez le faire en filtrant le paramètre query_posts () d'origine avec le filtre 'parse_query'. De cette façon, vous ne disposez que de la requête originale, originale, désirable, plutôt que de faire une seconde requête pour la remplacer maladroitement. query_posts () n'est JAMAIS LA VOIE !! JAMAIS!
jerclarke
22
Il y a une incroyable explication géniale de query_posts écrite par John James Jacoby sur le blog developer.wordpress.com qui balaie toutes ces réponses hors de l'eau. Le principal point: query_postsne pas modifier la boucle principale du tout, il remplace ce après avoir déjà exécuté. La meilleure façon de modifier la boucle principale consiste à pre_get_postsutiliser un filtre. developer.wordpress.com/2012/05/14/…
Dan Gayle
65

query_posts- Vous ne devriez jamais utiliser query_posts. Mis à part ce que @Rarst a dit, le problème le plus grave query_postsest qu'il casse l'objet de requête principal (stocké dans $wp_query). Un grand nombre de plugins et de code personnalisé reposent sur l'objet de requête principal. Par conséquent, le fait de casser l'objet de requête principal signifie que vous cassez les fonctionnalités des plugins et du code personnalisé. Une de ces fonctions est la très importante fonction de pagination. Par conséquent, si vous cassez la requête principale, vous cassez la pagination.

Pour prouver à quel point query_postsun modèle est mauvais , procédez comme suit et comparez les résultats

var_dump( $wp_query );
query_posts( '&posts_per_page=-1' );
var_dump( $wp_query );

get_postset WP_Queryconstituent le moyen approprié de créer des requêtes secondaires ( telles que des publications connexes, des curseurs, du contenu en vedette et du contenu sur des pages de couverture statiques ) avec. Il convient de noter que vous ne devez utiliser aucun des deux en faveur de la requête principale sur la page d'accueil, une page unique ou tout type de page d'archive, car cela casserait la fonctionnalité de la page. Si vous devez modifier la requête principale, utilisez pre_get_postspour cela, et non une requête personnalisée. ( UPDATE: pour les pages de garde statiques et les pages vraies, voir Utilisation de pre_get_posts sur les pages vraies et les pages de couverture statiques *)

Essentiellement, WP_Queryest utilisé par la requête principale et est également utilisé par get_posts, mais bien que des get_posts()utilisations WP_Query, il y a quelques différences

  • get_postssont plus rapides que WP_Query. La marge dépend du nombre total de messages du site. La raison en est, get_postspasse 'no_found_rows' => truepar défaut à WP_Queryqui saute / légalement rompt la pagination. Avec 'no_found_rows' => true, WP_Queryobtient le nombre de messages demandés, puis abandonne. Par défaut, il recherche davantage tous les messages correspondant à la requête afin de calculer la pagination.

    Pour cette raison, get_posts()ne devrait être utilisé que pour les requêtes non paginées. Paginer get_postsest vraiment un gros bazar. WP_Querydevrait être utilisé pour toutes les requêtes paginées

  • get_posts()ne sont pas influencés par les posts_*filtres là où ils WP_Querysont influencés. La raison en est que get_posts, par défaut, passe 'suppress_filters' => trueàWP_Query

  • get_postsa quelques paramètres supplémentaires comme include, exclude, numberpostset category. Ces paramètres sont modifiés en paramètres valides WP_Queryavant d'être passés à WP_Query. includese transforme en post__in, excludeen post__not_in, categoryen catet numberpostsen posts_per_page. Juste une note, tous les paramètres qui peuvent être passés à WP_Queryfonctionne avec get_posts, vous pouvez ignorer et ne pas utiliser les paramètres par défaut deget_posts

  • get_postsrenvoie uniquement la $postspropriété de WP_Querywhile WP_Queryrenvoie l'objet complet. Cet objet est très utile quand il s’agit de conditions, de pagination et d’autres informations utiles pouvant être utilisées dans la boucle.

  • get_postsn'utilise pas la boucle, mais une foreachboucle pour afficher les messages. En outre, aucune balise de modèle n'est disponible par défaut. setup_postdata( $post )doit être utilisé pour rendre les balises de modèle disponibles. WP_Queryutilise la boucle et les balises de modèle sont disponibles par défaut

  • get_postspasse 'ignore_sticky_posts' => 1à WP_Query, donc get_postsignore par défaut les posts collants

Sur la base de ce qui précède, utilisez-vous get_postsou WP_Querydécidez-vous et qu'avez-vous besoin de la requête? Ce qui précède devrait vous guider dans votre choix

Pieter Goosen
la source
1
J'aimerais pouvoir avoir des réponses préférées. Cela explique tellement.
Patrik Alienus
1
Grande explication! "get_posts () doit être utilisé uniquement pour les requêtes non paginées. Paginer"
Bullyen
32

La différence fondamentale est qu’il query_posts()s’agit en réalité uniquement de modifier la boucle en cours. Une fois que vous avez terminé, il est nécessaire de réinitialiser la boucle et de l’envoyer en joyeux chemin. Cette méthode est aussi un peu plus facile à comprendre, tout simplement parce que votre "requête" est essentiellement une chaîne d’URL que vous transmettez à la fonction, comme ceci:

query_posts('meta_key=color&meta_value=blue'); 

D'autre part, WP_Queryc'est plus un outil à usage général et ressemble plus à l'écriture directe de requêtes MySQL que ce query_posts()n'est le cas. Vous pouvez également l'utiliser n'importe où (pas seulement dans la boucle) et cela n'interfère pas avec les requêtes post en cours d'exécution.

J'ai tendance à utiliser WP_Queryplus souvent, comme cela arrive. Vraiment, cela dépendra de votre cas particulier.

nickmjones
la source
15

Il n'y a tout simplement pas besoin d'utiliser query_posts(). Tout ce qu'il fait, c'est instancier un nouvel objet WP_Query et le réaffecter global wp_query.

Pour référence, ce qui suit est cette query_posts()fonction réelle .

 function query_posts($query) {
        $GLOBALS['wp_query'] = new WP_Query();
        return $GLOBALS['wp_query']->query($query);
    }

Instanciez votre propre objet WP_Query si vous souhaitez créer un script de requête personnalisé détaillé. Ou utilisez get_posts()si tout ce que vous avez à faire est une légère manipulation ici et là.

Dans les deux cas, je vous recommande vivement vous faire une faveur et d' aller wp_includes/query.phpet lisant attentivement la WP_Queryclasse.

RebelPhoenix
la source
14

Assurez-vous que vous utilisez wp_reset_query()après avoir utilisé, query_posts()car cela affectera également le résultat de la requête.

Bindiya Patoliya
la source
10

Si je me souviens bien d'avoir lu, l'essentiel est "la boucle" WP_Querydans les fichiers de base, mais d'une manière plus facile à comprendre.

tw2113
la source
6
  • query_posts () : peut être utilisé dans un seul et même cas si vous devez modifier une requête principale. Cela définit beaucoup de variables globales;
  • get_posts () : il est très similaire en mécanique et accepte les mêmes arguments, mais retourne un tableau de posts
  • WP_Query : vous pouvez créer et travailler avec son propre objet. Un peu plus complexe, moins de restrictions, il est sûr de l’utiliser n'importe où.
dalveer
la source
-6

Je dirais ne pas utiliser get_posts()dans un plugin. Il impose des filtres très restrictives dans certains cas (set de suppress_filters, ignore_sticky_posts, etc.) doivent être utilisés probablement dans un thème quand vous voulez quelque chose rapide.

m4olivei
la source