Ho provato ad applicare la risposta di @Manny Fleurmond e come @Jake non sono riuscito a farlo funzionare anche dopo aver corretto l'errore di battitura che 'orderby' => 'meta_key'
dovrebbe essere 'orderby' => 'meta_value'
. (E per completezza che dovrebbe essere 'posts_per_page'
non 'post_per_page'
, ma che non pregiudica la questione di essere guardato.)
Se guardi alla query SQL effettivamente generata dalla risposta di @Manny Fleurmond (dopo aver corretto i refusi) questo è ciò che ottieni:
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
Questo illustra il modo in cui WP sta analizzando le query vars: sta creando una tabella per ogni clausola meta_query, quindi capendo come unirle e cosa ordinare. L'ordinamento funzionerebbe correttamente se si utilizzava una sola clausola con 'compare' => 'EXISTS'
, ma unendo la seconda 'compare' => 'NOT EXISTS'
clausola con OR (come dobbiamo) si incasina l'ordinamento. Il risultato è che LEFT JOIN è usato per unire sia la prima clausola / tabella che la seconda clausola / tabella - e il modo in cui WP mette insieme tutto ciò significa che la tabella creata usando 'compare' => 'EXISTS'
viene effettivamente popolata con meta_valori da QUALSIASI campo personalizzato, non solo il 'custom_author_name'
campo a cui siamo interessati. Quindi penso che ordinare per quella clausola / tabella fornirà i risultati desiderati solo se il particolare post_type di 'news' ha un solo campo personalizzato.
La soluzione che ha funzionato per la mia situazione è stata quella di ordinare dall'altra clausola / tabella - quella NON ESISTE. Apparentemente controintuitivo, lo so, ma a causa del modo in cui WP analizza le query, questa tabella meta_value
è popolata solo dal campo personalizzato che stiamo cercando.
(L'unico modo in cui l'ho capito era eseguendo l'equivalente di questa query per il mio caso:
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
Tutto quello che ho fatto è stato modificare le colonne mostrate e rimuovere la clausola GROUP BY. Questo poi mi ha mostrato cosa stava succedendo - che la colonna postmeta.meta_value stava estraendo i valori da tutti i meta_key, mentre la colonna mt1.meta_value stava estraendo solo i meta_valori dal campo personalizzato delle notizie.)
La soluzione
Come dice @Manny Fleurmond, è la prima clausola utilizzata per l'ordine, quindi la risposta è solo scambiare le clausole, dando questo:
$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);
In alternativa puoi creare le clausole array associativi e ordinare in base alla chiave corrispondente, in questo modo:
$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'
, ha cambiato l'ordine, ma non aveva nulla a che fare con il meta field reale.