Wp_query peut-il renvoyer des messages meta en une seule demande?
-
-
Le WP_Query standardne renvoiepas demétadonnées depublication.Les seules options que vous avez sont de: 1)exécuter `get_post_meta` sur des clésindividuelles,2)exécuter`get_post_custom`pour obtenirtous les champspersonnalisés d'un articleen un seul coup,ou 3) créer votrepropre requêteen utilisant la classe $ wpdb (`get_results () `)pour construire votrepropre objet de retour.(documentation de la classe $ wpdb: http://codex.wordpress.org/Class_Reference/wpdb)The standard WP_Query does not return a posts meta data. The only options you have are to: 1) run `get_post_meta` on individual keys, 2) run `get_post_custom` to get all of a posts custom fields in one shot, or 3) create your own query using the $wpdb class (`get_results()`) to build your own return object. ($wpdb class documentation: http://codex.wordpress.org/Class_Reference/wpdb)
- 2
- 2014-12-12
- BODA82
-
4 réponses
- votes
-
- 2014-12-12
Par défaut,
WP_Query
renvoie lanormeWP_Post
objetspour lesmessagesinterrogés. Je crois qu'avec une réécritureet une utilisationintelligentes desfiltres donnés dansWP_Query
,vouspouvez ajouter des objets autableau d'objetsWP_Post
retourné.Est-ce que ce seraperformant? Àmon avis,celanuira davantage auxperformances car vous devrezjoindre les résultats dans votre requête car les champspersonnalisésne sontpasenregistrés dans latable
wp_posts
,mais dans latablewp_postmeta
La récupération de laméta depublicationesttrès rapideet nenécessite aucuneinstance supplémentaire de
WP_Query
. Vouspouvez simplement appeler le champpersonnalisé avecget_post_meta()
. WordPress a ététrès attentionné lorsque les champspersonnalisés ont étéintroduits. Ils ont ajouté un cachepour lesmettreen cache,donc que vousinterrogiez 1 ou 100 champspersonnalisés,vous accédez à labase de données unefois,très rapidement. Pour untest completet uneexplication,consultez cepost quej'ai récemment rédigé sur ce sujet.Àmon avis,l'appel debase de données supplémentaireet letemps réelpasséen valent lapeine etplus rapidement que la réécriture de
WP_Query
demanière àinclure des champspersonnalisés dans l'objet depublication standard renvoyépar$posts
By default,
WP_Query
returns the standardWP_Post
objects for the posts being queried. I believe with some clever rewrite and use of the filters given inWP_Query
you can add objects to the returnedWP_Post
objects array.Will this be performant? In my opinion, it will hurt performance more as you will need to join results in your query as custom fields are not saved in the
wp_posts
table, but in thewp_postmeta
tableRetrieving post meta is really fast and it does not require any extra instance of
WP_Query
. You can simply call the custom field withget_post_meta()
. WordPress was very thoughtful when the custom fields was introduced. They added a cache to cache them, so whether you are querying 1 or 100 custom fields, you are hitting the database once, superfast. For a complete test and explanation, see this post I have recently done on this subject.In my opinion, the extra database call and the actual time spent is worth it and faster than rewriting
WP_Query
in such a way to include custom fields in the standard post object returned by$posts
-
OK,merci,je vais choisir celui-ci comme accepté,maispour être honnête,ilesttellement compliqué d'appeler `get_post_meta ()`pour chaquemessage ... Jepréférerais qu'il y ait unmoyen de stocker des données supplémentaires soit directement dans leLatable `wp_posts`,ou dans unetable liée quin'estpas autant unmindf * ck que` wp_postsmeta` l'est.OK, thanks, I'll pick this one as accepted, but to be honest its just so much hassle calling `get_post_meta()` for every single post.. I'd rather there was a way to store additional data either directly in the `wp_posts` table, or in a related table which is not as much of a mindf*ck as `wp_postsmeta` is.
- 0
- 2014-12-12
- YemSalat
-
Ehbien,pour être honnête,que ce soiten appelant `get_post_meta ()` ouen tant qu'objet depublication,vous devrez l'appeler à chaquemessage.C'est lamême chose avec lesbalises demodèle comme `the_content ()`,vous devez l'appeler sur chaquemessage.Well, to be honest, whether calling `get_post_meta()` or it as a post object, you will need to call it on every post. It is the same with template tags like `the_content()`, you have to call it on every post.
- 0
- 2014-12-12
- Pieter Goosen
-
Cela signifie que si vous devez afficher 120 articles,vous aurez 120 requêtes supplémentaires dans votrepage?This means that if you have to show 120 posts you will have an extra 120 queries in your page?
- 2
- 2015-09-14
- chifliiiii
-
Toutes les donnéespostales sontenregistrées dans un cache,vousn'aurez doncpas de requêtes supplémentaires lorsque cal; lingpostmetaAll postdata get saved in an cache, so you will not have extra queries when cal;ling post meta
- 0
- 2015-09-14
- Pieter Goosen
-
Vous avez raison.Jefaisais référence àpost_thumbnailsmaisj'ai récemmenttrouvé update_post_thumbnail_cache ($the_query).Merci quandmêmepour la clarificationYou are right. I was referring to post_thumbnails but I recently found update_post_thumbnail_cache( $the_query ). Thanks anyway for the clarification
- 0
- 2015-09-14
- chifliiiii
-
- 2016-05-05
Cette question date deplus d'un an,maisj'ai lemêmeproblème,et voici unefonction qui ajoutera chaquemeta_valueet meta_key à l'objet $ wp_query,
au lieu d'interroger chaquemessagemeta dans laboucle while,cettefonctionfera une requête supplémentaire exemple:
"SELECTmeta_key,meta_value,post_id FROM $ wpdb->postmeta WHEREpost_id IN (1,2,3,4,5 ...)"
où (1,2,3,4,5 ...)est actuellementinterrogé sur les ID depublication de $ wp_query
if(!function_exists('add_query_meta')) { function add_query_meta($wp_query = "") { //return In case if wp_query is empty or postmeta already exist if( (empty($wp_query)) || (!empty($wp_query) && !empty($wp_query->posts) && isset($wp_query->posts[0]->postmeta)) ) { return $wp_query; } $sql = $postmeta = ''; $post_ids = array(); $post_ids = wp_list_pluck( $wp_query->posts, 'ID' ); if(!empty($post_ids)) { global $wpdb; $post_ids = implode(',', $post_ids); $sql = "SELECT meta_key, meta_value, post_id FROM $wpdb->postmeta WHERE post_id IN ($post_ids)"; $postmeta = $wpdb->get_results($sql, OBJECT); if(!empty($postmeta)) { foreach($wp_query->posts as $pKey => $pVal) { $wp_query->posts[$pKey]->postmeta = new StdClass(); foreach($postmeta as $mKey => $mVal) { if($postmeta[$mKey]->post_id == $wp_query->posts[$pKey]->ID) { $newmeta[$mKey] = new stdClass(); $newmeta[$mKey]->meta_key = $postmeta[$mKey]->meta_key; $newmeta[$mKey]->meta_value = maybe_unserialize($postmeta[$mKey]->meta_value); $wp_query->posts[$pKey]->postmeta = (object) array_merge((array) $wp_query->posts[$pKey]->postmeta, (array) $newmeta); unset($newmeta); } } } } unset($post_ids); unset($sql); unset($postmeta); } return $wp_query; } }
Un additioanal "postmeta" sera écrit dans chaque $ wp_query->posts [$i]
$wp_query->posts[0]->postmeta
Exemple avec 'someMetaKeyName'n'oubliezpas de mettre
add_query_meta()
à votrethèmefunctin.php$args = array ( 'post_type' => 'page', 'meta_key' => 'someMetaKeyName', ); // The Query $query = new WP_Query( $args ); if($wp_query->have_posts()) { $wp_query = add_query_meta($wp_query); $i = 0; while($wp_query->have_posts()) { $wp_query->the_post(); $post_id = get_the_id(); //Get $someMetaKeyName in current post foreach($wp_query->posts[$i]->postmeta as $k => $v) { switch($v->meta_key) { case('someMetaKeyName') : { $someMetaKeyName = $v->meta_value; break; } } } //Your Code here //Example echo isset($someMetaKeyName) ? '<h3>'.$someMetaKeyName.'</h3>' : ''; $i++; } }
This question is more than 1 year old, but I have the same problomlem, and here is function that will add each meta_value and meta_key to $wp_query object,
instead of query each post meta in while loop, this function will do One extra query example:
"SELECT meta_key, meta_value, post_id FROM $wpdb->postmeta WHERE post_id IN (1,2,3,4,5...)"
where (1,2,3,4,5...) is curently quered post IDs from $wp_query
if(!function_exists('add_query_meta')) { function add_query_meta($wp_query = "") { //return In case if wp_query is empty or postmeta already exist if( (empty($wp_query)) || (!empty($wp_query) && !empty($wp_query->posts) && isset($wp_query->posts[0]->postmeta)) ) { return $wp_query; } $sql = $postmeta = ''; $post_ids = array(); $post_ids = wp_list_pluck( $wp_query->posts, 'ID' ); if(!empty($post_ids)) { global $wpdb; $post_ids = implode(',', $post_ids); $sql = "SELECT meta_key, meta_value, post_id FROM $wpdb->postmeta WHERE post_id IN ($post_ids)"; $postmeta = $wpdb->get_results($sql, OBJECT); if(!empty($postmeta)) { foreach($wp_query->posts as $pKey => $pVal) { $wp_query->posts[$pKey]->postmeta = new StdClass(); foreach($postmeta as $mKey => $mVal) { if($postmeta[$mKey]->post_id == $wp_query->posts[$pKey]->ID) { $newmeta[$mKey] = new stdClass(); $newmeta[$mKey]->meta_key = $postmeta[$mKey]->meta_key; $newmeta[$mKey]->meta_value = maybe_unserialize($postmeta[$mKey]->meta_value); $wp_query->posts[$pKey]->postmeta = (object) array_merge((array) $wp_query->posts[$pKey]->postmeta, (array) $newmeta); unset($newmeta); } } } } unset($post_ids); unset($sql); unset($postmeta); } return $wp_query; } }
Additioanal "postmeta" will be written to each $wp_query->posts[$i]
$wp_query->posts[0]->postmeta
Example with 'someMetaKeyName' don`t forget to put
add_query_meta()
to your theme functin.php$args = array ( 'post_type' => 'page', 'meta_key' => 'someMetaKeyName', ); // The Query $query = new WP_Query( $args ); if($wp_query->have_posts()) { $wp_query = add_query_meta($wp_query); $i = 0; while($wp_query->have_posts()) { $wp_query->the_post(); $post_id = get_the_id(); //Get $someMetaKeyName in current post foreach($wp_query->posts[$i]->postmeta as $k => $v) { switch($v->meta_key) { case('someMetaKeyName') : { $someMetaKeyName = $v->meta_value; break; } } } //Your Code here //Example echo isset($someMetaKeyName) ? '<h3>'.$someMetaKeyName.'</h3>' : ''; $i++; } }
-
J'adore cette solution.I love this solution.
- 0
- 2017-08-01
- Armstrongest
-
- 2017-02-14
J'aieu unproblème similaire récemment,je devais obtenir 7métadonnées àpartir d'untype depublicationpersonnalisé,maisj'avais égalementbesoin d'obtenir lemessageen fonction d'un élément demétadonnées.
J'ai donc créé l'instruction SQL suivante,je l'utilise souvent. J'espère que cela aidera quelqu'un d'autre. Je vaisessayer de l'expliquer dumieux queje peux.
global $wpdb; $pt = 'clients'; $mk = 'trainerid'; $mv = $pid; $mk1 = 'email'; $mk2 = 'phone'; $mk3 = 'gender'; $mk4 = 'dob'; $mk5 = 'photo'; $mk6 = 'registrationts'; $mk7 = 'activationts'; $ord = 'p.post_name ASC'; $sql = " SELECT p.ID, p.post_title AS fullname, pm1.meta_value AS email, pm2.meta_value AS phone, pm3.meta_value AS gender, pm4.meta_value AS dob, pm5.meta_value AS photo, pm6.meta_value AS regts, pm7.meta_value AS actemailts FROM {$wpdb->posts} p LEFT JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID AND pm.meta_key = '{$mk}' LEFT JOIN {$wpdb->postmeta} pm1 ON pm1.post_id = p.ID AND pm1.meta_key = '{$mk1}' LEFT JOIN {$wpdb->postmeta} pm2 ON pm2.post_id = p.ID AND pm2.meta_key = '{$mk2}' LEFT JOIN {$wpdb->postmeta} pm3 ON pm3.post_id = p.ID AND pm3.meta_key = '{$mk3}' LEFT JOIN {$wpdb->postmeta} pm4 ON pm4.post_id = p.ID AND pm4.meta_key = '{$mk4}' LEFT JOIN {$wpdb->postmeta} pm5 ON pm5.post_id = p.ID AND pm5.meta_key = '{$mk5}' LEFT JOIN {$wpdb->postmeta} pm6 ON pm6.post_id = p.ID AND pm6.meta_key = '{$mk6}' LEFT JOIN {$wpdb->postmeta} pm7 ON pm7.post_id = p.ID AND pm7.meta_key = '{$mk7}' WHERE pm.meta_value = '{$mv}' AND p.post_type = '{$pt}' AND p.post_status NOT IN ('draft','auto-draft') ORDER BY {$ord} "; $clients = $wpdb->get_results( $wpdb->prepare( $sql ), OBJECT );
D'abord,j'obtiens lesfonctions de labase de données wordpress avecglobal $ wpdb. Ensuite,j'ai défini leposttype avec $pt. Pour obtenir lemessage correct qui correspond à une valeur spécifique danspost_meta,j'ai défini le $mk (meta_key)
Ensuite,j'ai défini la variable $mv (meta_value). (dans ce cas,la valeurmeta correspond à unpostid)
$mk1- $mk7 sont lesméta_keys queje veux de chaquemessage. (Je vais saisir les valeurs dans l'instruction select)
Jefais aussi le 'ordrepar' une var,en définissant $ ord
L'instruction select seprésente comme suit: Je sélectionne l'identifiantet lepost_title dans le POST ou "p".
Ensuite,je sélectionnetoutes lesmétadonnées dontj'aibesoinen les sélectionnant avecpm1. ->pm.7et en récupérant lesmeta_valueet en les renommant (AS)pour qu'il soitplus lisible lors de la récupération des données demon objet.
Je crée unejointure àgauchepour lesmétadonnées dontj'aibesoinpourfaire correspondre lemessage. (pm)
Je crée 7jointures degauchepour chacune desmétadonnées quej'aibesoin de récupérer. (pm1-pm7)
L'instruction WHEREestbasée sur lepremier LEFT JOIN (pm) afin qu'elle sache queje n'aibesoin que desmessages où lesmétadonnées correspondent.
J'ajoute également un "ET"pour letype demessageet pour lespost_status quine sontpas desbrouillons. (donc seulement les articlespubliés)
Enfin,j'ajoute la clause 'orderby'.
Celafonctionne rapidementet avec lesindexintégrés dans Wordpress,donc cela sembleefficace.
Jene saispas si quelque choseestmieux que ça,mais si c'est le cas,j'aimeraisbien l'utiliser.
J'espère que cela vous aidera.
Marcus
I had a similar problem recently, I needed to get 7 pieces of metadata from a custom post type, but also needed to get the post based on a piece of metadata.
So I created the following SQL statement, I use it often. Hopefully it will help someone else. I'll try and explain it as best I can.
global $wpdb; $pt = 'clients'; $mk = 'trainerid'; $mv = $pid; $mk1 = 'email'; $mk2 = 'phone'; $mk3 = 'gender'; $mk4 = 'dob'; $mk5 = 'photo'; $mk6 = 'registrationts'; $mk7 = 'activationts'; $ord = 'p.post_name ASC'; $sql = " SELECT p.ID, p.post_title AS fullname, pm1.meta_value AS email, pm2.meta_value AS phone, pm3.meta_value AS gender, pm4.meta_value AS dob, pm5.meta_value AS photo, pm6.meta_value AS regts, pm7.meta_value AS actemailts FROM {$wpdb->posts} p LEFT JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID AND pm.meta_key = '{$mk}' LEFT JOIN {$wpdb->postmeta} pm1 ON pm1.post_id = p.ID AND pm1.meta_key = '{$mk1}' LEFT JOIN {$wpdb->postmeta} pm2 ON pm2.post_id = p.ID AND pm2.meta_key = '{$mk2}' LEFT JOIN {$wpdb->postmeta} pm3 ON pm3.post_id = p.ID AND pm3.meta_key = '{$mk3}' LEFT JOIN {$wpdb->postmeta} pm4 ON pm4.post_id = p.ID AND pm4.meta_key = '{$mk4}' LEFT JOIN {$wpdb->postmeta} pm5 ON pm5.post_id = p.ID AND pm5.meta_key = '{$mk5}' LEFT JOIN {$wpdb->postmeta} pm6 ON pm6.post_id = p.ID AND pm6.meta_key = '{$mk6}' LEFT JOIN {$wpdb->postmeta} pm7 ON pm7.post_id = p.ID AND pm7.meta_key = '{$mk7}' WHERE pm.meta_value = '{$mv}' AND p.post_type = '{$pt}' AND p.post_status NOT IN ('draft','auto-draft') ORDER BY {$ord} "; $clients = $wpdb->get_results( $wpdb->prepare( $sql ), OBJECT );
First I get the wordpress database functions with global $wpdb. Then I set the posttype with $pt. To get the correct post that matches a specific value in post_meta, I set the $mk (meta_key)
Then I set the $mv (meta_value) var. (in this case the meta value matches a postid)
$mk1-$mk7 are the meta_keys I want from each post. (I'll grab the values in the select statement)
I also make the 'order by' a var, by setting $ord
The select statement goes as follows: I select the post ID and the post_title from the POST or 'p.'
Then I select all the metadata I need selecting them with pm1. -> pm.7 and grabbing the meta_value and renaming them ( AS ) so it's more readable when retrieving the data from my object.
I create a LEFT JOIN for the meta data I need to match to the post. (pm)
I create 7 left join's for each of the meta data I need to retrieve. (pm1-pm7)
The WHERE statement is based on the first LEFT JOIN (pm) so that it will know I need only the posts where the metadata matches.
I also add an 'AND' for the post type, and for the post_statuses that are not drafts. (so only published posts)
Finally I add the 'order by' clause.
This works fast and with the built-in indexes in Wordpress, so it seems efficient.
Don't know if something is better than this, but if it is, I'd love to use it.
Hope this helps.
Marcus
-
Merci,cet articleesttrès utile.J'ai créé une vue avectous les champsméta dontj'aibesoinet ilestmaintenanttrès rapideet facile d'obtenir les données queje veuxThanks, this post is very helpful. I created a view with all meta fields i need and now is very fast and easy to get any data i want
- 0
- 2017-11-23
- Liko
-
- 2014-12-12
Hey S'il vousplaîtessayez celui-ci,je pense que celafonctionnebien.
$args = array( 'post_type' => 'page', 'meta_key' => 'someMetaKeyName', 'meta_query' => array( array( 'key' => 'someMetaKeyName', 'type' => 'CHAR', ), ), ); $query = new WP_Query( $args );
Hey Please try this one I think it work fine.
$args = array( 'post_type' => 'page', 'meta_key' => 'someMetaKeyName', 'meta_query' => array( array( 'key' => 'someMetaKeyName', 'type' => 'CHAR', ), ), ); $query = new WP_Query( $args );
-
Quelleest la raisonpour laquelle vous avez également utilisé `meta_key`et`meta_query [] ['key'] `?What's the reason that you used `meta_key` and `meta_query[]['key']` as well?
- 0
- 2014-12-12
- kaiser
-
Non,celane fonctionnepaset ramène letableau desmessages sansméta qui leurest associé.No, this does not work and brings back the array of posts without meta associated with them.
- 1
- 2014-12-12
- YemSalat
-
`meta_key`et/ou`meta_query`ne modifientpas letype de résultats renvoyés,seulement la requêteelle-même.`meta_key` and/or `meta_query` do not modify the type of results returned, only the query itself.
- 4
- 2014-12-12
- BODA82
Je voudrais créer une wp_query qui renverrait laméta des articles dans letableau
posts
.Cela renvoie quelque chose comme:
Comme vouspouvez le voir,les articlesne contiennentpas demétadonnées,est-ilpossible d'inclure également lesmétadonnées dans letableau renvoyé?
PS Jene veuxpas de wp_queries supplémentairespour des raisons deperformances.