Requête pour trier une liste par clé méta en premier (si elle existe), et afficher les messages restants sans clé méta triés par titre
-
-
Surpris,l'approchemeta_queryn'apasfonctionné,mais làencore,vousne pouvezpas commanderparméta valeur avec unemeta_query sans avoir l'ensemblemeta_key.Surprised the meta_query approach didn't work, but then again you can't orderby meta value with a meta_query without having the meta_key set.
- 0
- 2013-12-17
- sanchothefat
-
Jepense que c'est leproblème quej'ai.J'aifinalementfaitfonctionner uneméta-requête: `` 'meta_query'=> array ( 'relation'=> 'OU', array (//vérifie si la date a été remplie 'key'=> 'date_publication', 'compare'=> '!=', 'value'=> date ('A-m-j'), ), array (//si aucune daten'a été ajoutée,afficher également ces articles 'key'=> 'date_publication', 'value'=> date ('A-m-j'), 'compare'=> 'N'EXISTE PAS' ) ),`mais la commandene fonctionnepas: \I think that is the problem I am having. I did finally get a meta query working: `'meta_query' => array( 'relation' => 'OR', array( //check to see if date has been filled out 'key' => 'publication_date', 'compare' => '!=', 'value' => date('Y-m-d'), ), array( //if no date has been added show these posts too 'key' => 'publication_date', 'value' => date('Y-m-d'), 'compare' => 'NOT EXISTS' ) ),` but the ordering isn't working :\
- 0
- 2013-12-17
- CSSgirl
-
oui,la commande reposemalheureusement surmeta_keyen dehors detax_query.Ma réponse ci-dessouspourrait cependant aider.yep, ordering relies upon meta_key being set outside of the tax_query unfortunately. My answer below might help though.
- 0
- 2013-12-18
- sanchothefat
-
5 réponses
- votes
-
- 2013-12-18
Merci àtouspour votre aide!
Enfin de compte,la requête ci-dessousm'a donné les résultats queje souhaitais - qui était d'afficheret detrier lesmessagespar un champpersonnalisé de "publication_date"en premier -en lestriantpar date,et s'il y avaitplusieurs de lamême date (parexemple,4marquéjuin 2013),il lestrieraitpartitre. Ensuite,après avoirparcourutous les articles dont la date depublicationest renseignée,ilparcourra ànouveau les articles restants,par ordre alphabétique detitre.
Celame permet d'obtenir les résultats définis dans lamême requêteet de conservermapagination:
$term = get_queried_object(); the_post(); $wp_query = new WP_Query( array( 'post_type' => 'resource', 'tax_query' => array( array( 'taxonomy' => 'resource_types', 'field' => 'slug', 'terms' => $term->name, )), 'meta_query' => array( 'relation' => 'OR', array( //check to see if date has been filled out 'key' => 'publication_date', 'compare' => '=', 'value' => date('Y-m-d') ), array( //if no date has been added show these posts too 'key' => 'publication_date', 'value' => date('Y-m-d'), 'compare' => 'NOT EXISTS' ) ), 'meta_key' => 'publication_date', 'orderby' => 'meta_value title', 'order' => 'ASC', 'paged' => $paged, 'posts_per_page' => '10', ));
Thank you everyone for your help!
In the end the query below got me the results I desired - which was to show and sort the posts by a custom field of "publication_date" first - sorting by the date, and if there were multiple of the same date (say, 4 marked June 2013), it would sort those by title. Then, after it runs through all the posts that have the Publication Date filled in it will loop through again the remaining posts, alphabetically by title.
This gets me the results set in the same query, and keeps my pagination:
$term = get_queried_object(); the_post(); $wp_query = new WP_Query( array( 'post_type' => 'resource', 'tax_query' => array( array( 'taxonomy' => 'resource_types', 'field' => 'slug', 'terms' => $term->name, )), 'meta_query' => array( 'relation' => 'OR', array( //check to see if date has been filled out 'key' => 'publication_date', 'compare' => '=', 'value' => date('Y-m-d') ), array( //if no date has been added show these posts too 'key' => 'publication_date', 'value' => date('Y-m-d'), 'compare' => 'NOT EXISTS' ) ), 'meta_key' => 'publication_date', 'orderby' => 'meta_value title', 'order' => 'ASC', 'paged' => $paged, 'posts_per_page' => '10', ));
-
Agréable.Jen'aijamaispensé àexécuter deux `meta_query` sur lamême clé!Nice. I never thought to run two `meta_query` on the same key!
- 1
- 2013-12-19
- GhostToast
-
Pourmoi (en utilisant WordPress 4.1.1),sije définis `` ``meta_key '',celane l'inclutpas automatiquementmême avec `` NOT EXISTS ''.J'espère vraiment queje fais quelque chose demal.For me (using WordPress 4.1.1), if I set ```meta_key``` it automatically doesn't include it even with ```NOT EXISTS```. I really hope I'm doing something wrong.
- 6
- 2015-03-24
- Ryan Taylor
-
@RyanTayloridemici -meta_keyne doitpas être défini dans la requêtepour que celafonctionne,maisil semble être ordonné correctementpar valeurmétamême lorsque la clémétan'estpas définie.@RyanTaylor same here - meta_key must not be set in the query for this to work, but it does appear to order correctly by meta value even when meta key is not set.
- 1
- 2016-01-21
- jammypeach
-
Comme les commentaires ci-dessus,pour WP 4.1+,supprimez ou commentez ``meta_key '=>'publication_date ',`.As above comments, for WP 4.1+ remove or comment out `'meta_key' => 'publication_date',`.
- 2
- 2016-07-14
- MikeiLL
-
Tout ce quej'avais àfaire était de supprimer la cléméta.Beaucoup de réponsesinutiles sur stackoverflowmaismerci !!Literally all I had to do was remove the meta key. Lots of unhelpful answers on stackoverflow but thank you!!
- 0
- 2020-07-11
- Jacob Raccuia
-
- 2016-02-26
Quelques annéesplustard,le codepubliépar CSSGirlne fonctionnaitpaspourmoi caril y avait desmessages quin'avaientpas la cléméta ou la cléméta était vide,c'est ce quej'ai dûfairepour avoirtous lesmessagestriéspar dateet afficher ceux avec une valeur de clémétaen premier:
$args = array( 'post_type' => $type, 'post_status' => 'publish', 'nopaging' => TRUE, 'meta_query' => array( 'relation' => 'OR', array( 'key' => $meta_key, 'compare' => 'NOT EXISTS', ), array( 'relation' => 'OR', array( 'key' => $meta_key, 'value' => 'on', ), array( 'key' => $meta_key, 'value' => 'on', 'compare' => '!=', ), ), ), 'orderby' => array( 'meta_value' => 'DESC', 'date' => 'DESC' ), );
Few years later, the code posted by CSSGirl wasn't working for me because there were some posts that didn't have the meta key or the meta key was empty so this is what I had to do to have all the posts ordered by date and show the ones with a meta key value display first:
$args = array( 'post_type' => $type, 'post_status' => 'publish', 'nopaging' => TRUE, 'meta_query' => array( 'relation' => 'OR', array( 'key' => $meta_key, 'compare' => 'NOT EXISTS', ), array( 'relation' => 'OR', array( 'key' => $meta_key, 'value' => 'on', ), array( 'key' => $meta_key, 'value' => 'on', 'compare' => '!=', ), ), ), 'orderby' => array( 'meta_value' => 'DESC', 'date' => 'DESC' ), );
-
- 2013-12-17
Jepense que vous auriezbesoin defaire 2boucles séparées.Vouspouvez capturertous lesmessagestrouvés dans lapremièreboucleet lesexclure de laboucle secondaire assezfacilement:
$found_posts = array(); while($loop->have_posts()): $loop->the_post(); // loop stuff $found_posts[] = get_the_id(); endwhile; wp_reset_query(); $args = array( // other args 'post__not_in' => $found_posts, );
Ensuite,lancez votre deuxièmeboucle.
I think you'd need to do 2 separate loops. You can capture all the posts found in the first loop and exclude them from the secondary loop easily enough:
$found_posts = array(); while($loop->have_posts()): $loop->the_post(); // loop stuff $found_posts[] = get_the_id(); endwhile; wp_reset_query(); $args = array( // other args 'post__not_in' => $found_posts, );
Then run your second loop.
-
Essayer çamaintenant,merci.Vousfera savoir si celafonctionne!Trying this now, thanks. Will let you know if it works!
- 0
- 2013-12-17
- CSSgirl
-
cela afonctionné -mais cela a cassé lapagination - uneidée commentfairefonctionner cela?Voici à quoi cela ressemblemaintenant: `echopaginate_links (array ( 'base'=> str_replace ($big,'% #%',esc_url (get_pagenum_link ($big))), 'format'=> '?page=% #%', 'current'=>max (1,get_query_var ('paged')), 'total'=> $publication_query->max_num_pages, 'prev_text'=> __ ('Précédent|'), 'next_text'=> __ ('| Next'), )); »this worked - but it broke the pagination - any idea how to get this to work? Here's what it looks like now: `echo paginate_links( array( 'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ), 'format' => '?page=%#%', 'current' => max( 1, get_query_var('paged') ), 'total' => $publication_query->max_num_pages, 'prev_text' => __('Previous |'), 'next_text' => __('| Next'), ) );`
- 1
- 2013-12-17
- CSSgirl
-
Hmm.Pas queje puissepenser.Hmm. Not that I can think of.
- 0
- 2013-12-17
- GhostToast
-
- 2013-12-17
Y a-t-il une raisonpour laquelle vousne pouviezpas appliquer la clémétapublication_datepourexisterpour chaquemessage avec une valeur vide?
Donc,dans votre action
save_post
,vous ajouteriez/mettriez àjour la cléméta,que la valeur$_POST
soit vide ounon.Vous devrezexécuter un script demise àjourpourparcourir vos anciens articleset ajouter la clé avec une valeur vide,parexemple:
add_action( 'admin_init', 'update_old_posts' ); function update_old_posts() { if ( ! isset( $_GET[ 'update_old_posts' ] ) ) return; foreach( get_posts() as $post ) { if ( false === get_post_meta( $post->ID, 'publication_date', true ) ) { update_post_meta( $post->ID, 'publication_date', '' ); echo "Updated {$post->post_title} <br />"; } } die; }
Exécutez-leen accédant à http://example.com/wp-admin/?update_old_posts
Ensuite,vouspouvez utiliser lamême requête que vous. Vous voudrezpeut-être ajouter unfiltre supplémentairepour vouspermettre detrierpar différentes colonnes dans différentes directions,il serait logiquepourmoi detrierpar datepar ordre décroissantet partitrepar ordre croissant.
add_filter( 'posts_orderby', 'multicolumn_orderby', 10, 2 ); function multicolumn_orderby( $orderby, $query ) { global $wpdb; // check it's the right query if ( $query->get( 'meta_key' ) == 'publication_date' ) { $orderby = "$wpdb->postmeta.meta_value+0 DESC, $wpdb->posts.post_title ASC"; } return $orderby; }
Is there any reason you couldn't enforce the publication_date meta key to exist for every post just with an empty value?
So in your
save_post
action you would add/update the meta key whether the$_POST
value is empty or not.You would have to run an update script to loop over your older posts and add the key with an empty value eg:
add_action( 'admin_init', 'update_old_posts' ); function update_old_posts() { if ( ! isset( $_GET[ 'update_old_posts' ] ) ) return; foreach( get_posts() as $post ) { if ( false === get_post_meta( $post->ID, 'publication_date', true ) ) { update_post_meta( $post->ID, 'publication_date', '' ); echo "Updated {$post->post_title} <br />"; } } die; }
Run it by browsing to http://example.com/wp-admin/?update_old_posts
Then you can use the same query as you have. You may want to add an extra filter to enable you to order by different columns in different directions, it would make to sense to me to sort by date in descending order and title in ascending order.
add_filter( 'posts_orderby', 'multicolumn_orderby', 10, 2 ); function multicolumn_orderby( $orderby, $query ) { global $wpdb; // check it's the right query if ( $query->get( 'meta_key' ) == 'publication_date' ) { $orderby = "$wpdb->postmeta.meta_value+0 DESC, $wpdb->posts.post_title ASC"; } return $orderby; }
-
Hmm,je n'y aipaspensé.Je vaisessayeret voir comment ça sepasse,merci!Hmm, I didn't think of that. I'm going to give that a try and see how it goes, thanks!
- 0
- 2013-12-17
- CSSgirl
-
- 2015-03-25
J'ai créé une clause wherepersonnalisée. Je l'aitestéen utilisant
$wp_query->request
juste avantmaboucleprincipale,je ne connaispas vraiment SQLtrèsbien,mais cela a sembléfairefonctionner les choses.add_action('pre_get_posts', 'add_trending_sort', 11, 1); function add_trending_sort($query){ if(!$query->is_main_query()) return; //Overwrite query arguments $query->set('meta_query', array( array( 'key' => 'TRENDING', //'value' => 'asdfasdf',//may need a value for older versions of WordPress 'compare' => 'NOT EXISTS', ) )); $query->set('orderby', 'meta_value_num date'); $query->set('order', 'DESC'); } add_filter('posts_where', 'add_trending_where'); function add_trending_where($where = ''){ global $wpdb, $wp_query; if(!$wp_query->is_main_query())//Not sure if this really works. Should be OK return $where; $where .= " OR ( $wpdb->postmeta.meta_key = 'TRENDING' )"; // Don't run this twice remove_filter('posts_where', 'add_trending_where'); return $where; }
Vouspouvez également définir
compare
sur'EXISTS'
et changer la ligne dans add_trending_whereen$where .= " OR ($wpdb->postmeta.post_id IS NULL)";
. Ensuite,vousn'aurez qu'à changer la valeur de la clé à un seulendroit. Encore unefois,faites écho à la$wp_query->request
et jouez si vous voulezmieux comprendre cela ou l'ajuster.EDIT: Je viens de remarquer que celane fonctionnepas si
meta_key
est défini sur la requête. Vouspouvez utiliser$query->set('meta_key', NULL);
si vous devez.EDIT 2: Je l'aifaitfonctionner avec laméthode ci-dessus. Pour une raison quelconque,cen'étaitpas au début (peut-être quemeta_key a été défini ...je ne saispas).
add_action('pre_get_posts', 'add_trending_sort', 11, 1); function add_trending_sort($query){ // Bail if not the main "hidden" query, as opposed to a 'new WP_Query()' call if(!$query->is_main_query()) return; // Set meta_query to get shares for orderby, and also get non-shared content. $query->set('meta_query', array( 'relation' => 'OR', array( 'key' => 'TRENDING', 'compare' => 'NOT EXISTS', ), array( 'key' => 'TRENDING', 'compare' => 'EXISTS', ) )); //$query->set('meta_key', NULL); $query->set('orderby', array('meta_value_num' => 'DESC', 'date' => 'DESC')); }
I created a custom where clause. I tested it using
$wp_query->request
right before my main loop, I don't really know SQL that well, but this seemed to get things working.add_action('pre_get_posts', 'add_trending_sort', 11, 1); function add_trending_sort($query){ if(!$query->is_main_query()) return; //Overwrite query arguments $query->set('meta_query', array( array( 'key' => 'TRENDING', //'value' => 'asdfasdf',//may need a value for older versions of WordPress 'compare' => 'NOT EXISTS', ) )); $query->set('orderby', 'meta_value_num date'); $query->set('order', 'DESC'); } add_filter('posts_where', 'add_trending_where'); function add_trending_where($where = ''){ global $wpdb, $wp_query; if(!$wp_query->is_main_query())//Not sure if this really works. Should be OK return $where; $where .= " OR ( $wpdb->postmeta.meta_key = 'TRENDING' )"; // Don't run this twice remove_filter('posts_where', 'add_trending_where'); return $where; }
Alternatively, you could set
compare
to'EXISTS'
and change the line in add_trending_where to$where .= " OR ($wpdb->postmeta.post_id IS NULL)";
. Then you'd only have to change the value of the key in one place. Again, echo$wp_query->request
and play around if you want understand this better or tweak it.EDIT: I just noticed this does not work if
meta_key
is set on the query. You could use$query->set('meta_key', NULL);
if you have to.EDIT 2: I got this working with the method above. For some reason it wasn't at first (maybe meta_key was set... I don't know).
add_action('pre_get_posts', 'add_trending_sort', 11, 1); function add_trending_sort($query){ // Bail if not the main "hidden" query, as opposed to a 'new WP_Query()' call if(!$query->is_main_query()) return; // Set meta_query to get shares for orderby, and also get non-shared content. $query->set('meta_query', array( 'relation' => 'OR', array( 'key' => 'TRENDING', 'compare' => 'NOT EXISTS', ), array( 'key' => 'TRENDING', 'compare' => 'EXISTS', ) )); //$query->set('meta_key', NULL); $query->set('orderby', array('meta_value_num' => 'DESC', 'date' => 'DESC')); }
Jetravaille sur unmodèle depage determe detaxonomiepersonnalisé dans lequelnous voulons que les éléments connectés auterme soienttriéspar date depublication (champ de datepersonnalisé) -et s'il y aplusieurs éléments lemêmejour (formaté comme AAAA -MM-JJ)pourensuitetrier ceux-cipartitre,et enfintrierpartitre si le champpersonnalisén'apas été rempli (élémentsplus anciens).
Donc,je l'aiessayé de centaines defaçons différentes avec une WP_queryet elle renvoie laplupart des résultats commeje les veux -mais dans ce cas,ilne renvoie que les éléments qui ont lameta_key depublication_date. Tous les autres éléments sontignoréset ne sontpas affichés. J'aiessayé unemeta_queryen utilisant une relation de "ou"et j'ai comparé la date depublication à EXISTSet NOT EXISTS,mais celan'a donné aucun résultatpourmoi.
Deplus,le siteexécutetoujours la version 3.5.2et ilsne souhaitentpasmettre àjour.
Voicima requête laplus récente quime permet d'obtenir les articles dont le champpersonnalisépublication_dateest affiché dans lebon ordre:
J'ai égalementessayé d'utiliser wpdbet d'exécuter une requête SQL,maisje ne sais vraimentpas comment accomplir ce queje veux. Si quelqu'unpouvaitm'aider,ce seraitgénial!
Merci d'avance.