J'ai essayé d'appliquer la réponse de @Manny Fleurmond et comme @Jake, je n'ai pas pu le faire fonctionner même après avoir corrigé la faute de frappe qui 'orderby' => 'meta_key'
devrait être 'orderby' => 'meta_value'
. (Et pour être complet, cela ne devrait 'posts_per_page'
pas l' être, 'post_per_page'
mais cela n'affecte pas le problème examiné.)
Si vous regardez la requête SQL réellement générée par la réponse de @Manny Fleurmond (après avoir corrigé les fautes de frappe), voici ce que vous obtenez:
SELECT wp_{prefix}_posts.* FROM wp_{prefix}_posts
LEFT JOIN wp_{prefix}_postmeta ON (wp_{prefix}_posts.ID = wp_{prefix}_postmeta.post_id AND wp_{prefix}_postmeta.meta_key = 'custom_author_name' )
LEFT JOIN wp_{prefix}_postmeta AS mt1 ON ( wp_{prefix}_posts.ID = mt1.post_id )
WHERE 1=1 AND (
wp_{prefix}_postmeta.post_id IS NULL
OR
mt1.meta_key = 'custom_author_name'
) AND wp_{prefix}_posts.post_type = 'news' AND
(wp_{prefix}_posts.post_status = 'publish' OR wp_{prefix}_posts.post_author = 1 AND wp_{prefix}_posts.post_status = 'private')
GROUP BY wp_{prefix}_posts.ID ORDER BY wp_{prefix}_postmeta.meta_value ASC
Cela illustre la façon dont WP analyse les variables de requête: il crée une table pour chaque clause meta_query, puis détermine comment les joindre et comment commander. La commande fonctionnerait bien si vous n'utilisiez qu'une seule clause avec 'compare' => 'EXISTS'
, mais joindre la deuxième 'compare' => 'NOT EXISTS'
clause avec OR (comme nous devons) gâche la commande. Le résultat est que LEFT JOIN est utilisé pour joindre à la fois la première clause / table et la seconde clause / table - et la façon dont WP met tout ensemble signifie que la table créée à l'aide 'compare' => 'EXISTS'
est réellement remplie avec des méta-valeurs de N'IMPORTE QUEL champ personnalisé, pas seulement le 'custom_author_name'
champ qui nous intéresse. Je pense donc que la commande par cette clause / table ne donnera les résultats souhaités que si le post_type particulier de 'news' n'a qu'un seul champ personnalisé.
La solution qui a fonctionné pour ma situation a été de commander par l'autre clause / table - celle PAS EXISTE. Apparemment contre-intuitif, je sais, mais en raison de la façon dont WP analyse les variables de requête, c'est cette table qui meta_value
n'est remplie que par le champ personnalisé que nous recherchons.
(La seule façon dont j'ai compris cela était d'exécuter l'équivalent de cette requête pour mon cas:
SELECT wp_{prefix}_posts.ID, wp_{prefix}_postmeta.meta_value, mt1.meta_value FROM wp_{prefix}_posts
LEFT JOIN wp_{prefix}_postmeta ON (wp_{prefix}_posts.ID = wp_{prefix}_postmeta.post_id AND wp_{prefix}_postmeta.meta_key = 'custom_author_name' )
LEFT JOIN wp_{prefix}_postmeta AS mt1 ON ( wp_{prefix}_posts.ID = mt1.post_id )
WHERE 1=1 AND (
wp_{prefix}_postmeta.post_id IS NULL
OR
mt1.meta_key = 'custom_author_name'
) AND wp_{prefix}_posts.post_type = 'news' AND
(wp_{prefix}_posts.post_status = 'publish' OR wp_{prefix}_posts.post_author = 1 AND wp_{prefix}_posts.post_status = 'private')
ORDER BY wp_{prefix}_postmeta.meta_value ASC
Tout ce que j'ai fait est de modifier les colonnes affichées et de supprimer la clause GROUP BY. Cela m'a ensuite montré ce qui se passait - que la colonne postmeta.meta_value récupérait les valeurs de toutes les méta-clés, tandis que la colonne mt1.meta_value récupérait uniquement les méta-valeurs du champ personnalisé de news.)
La solution
Comme le dit @Manny Fleurmond, c'est la première clause qui est utilisée pour la commande, donc la réponse est juste d'échanger les clauses, en donnant ceci:
$args = array(
'post_type' => 'news',
'orderby' => 'meta_value',
'order' => 'ASC',
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'custom_author_name',
'compare' => 'NOT EXISTS'
),
array(
'key' => 'custom_author_name',
'compare' => 'EXISTS'
)
),
'posts_per_page' => -1
);
$query = new WP_Query($args);
Alternativement, vous pouvez rendre les clauses des tableaux associatifs et les trier par la clé correspondante, comme ceci:
$args = array(
'post_type' => 'news',
'orderby' => 'not_exists_clause',
'order' => 'ASC',
'meta_query' => array(
'relation' => 'OR',
'exists_clause' => array(
'key' => 'custom_author_name',
'compare' => 'EXISTS'
),
'not_exists_clause' => array(
'key' => 'custom_author_name',
'compare' => 'NOT EXISTS'
)
),
'posts_per_page' => -1
);
$query = new WP_Query($args);
'orderby' => 'meta_value'
, cela a changé l'ordre, mais cela n'avait rien à voir avec le champ méta réel.