Intenté aplicar la respuesta de @Manny Fleurmond y, al igual que @Jake, no pude hacerlo funcionar incluso después de corregir el error tipográfico que 'orderby' => 'meta_key'
debería ser 'orderby' => 'meta_value'
. (Y para completar, hay que 'posts_per_page'
no 'post_per_page'
, pero que no afecta a la cuestión está examinando.)
Si observa la consulta SQL realmente generada por la respuesta de @Manny Fleurmond (después de corregir los errores tipográficos), esto es lo que obtiene:
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
Esto ilustra la forma en que WP analiza los vars de consulta: está creando una tabla para cada cláusula meta_query, luego descubre cómo unirlos y por qué ordenarlos. El orden funcionaría bien si solo usara una sola cláusula con 'compare' => 'EXISTS'
, pero unir la segunda 'compare' => 'NOT EXISTS'
cláusula con OR (como debemos) arruina el orden. El resultado es que LEFT JOIN se usa para unir tanto la primera cláusula / tabla como la segunda cláusula / tabla, y la forma en que WP reúne todo significa que la tabla creada usando en 'compare' => 'EXISTS'
realidad se llena con meta_valores de CUALQUIER campo personalizado, no solo el 'custom_author_name'
campo en el que estamos interesados. Así que creo que ordenar por esa cláusula / tabla solo dará los resultados deseados si el post_type particular de 'noticias' solo tiene un campo personalizado único.
La solución que funcionó para mi situación fue ordenar por la otra cláusula / tabla, la NO EXISTENTE. Parece contradictorio, lo sé, pero debido a la forma en que WP analiza los vars de consulta, es en esta tabla donde meta_value
se completa solo el campo personalizado que buscamos.
(La única forma en que descubrí esto fue ejecutando el equivalente de esta consulta para mi 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
Todo lo que he hecho es cambiar las columnas que se muestran y eliminar la cláusula GROUP BY. Esto luego me mostró lo que estaba sucediendo: que la columna postmeta.meta_value estaba obteniendo valores de todas las meta_keys, mientras que la columna mt1.meta_value estaba obteniendo solo meta_valores del campo personalizado de noticias).
La solución
Como dice @Manny Fleurmond, es la primera cláusula que se usa para el pedido, por lo que la respuesta es simplemente cambiar las cláusulas, dando esto:
$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);
Alternativamente, puede hacer que las cláusulas sean matrices asociativas y se ordenen por la clave correspondiente, de esta manera:
$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'
, cambió el orden, pero no tenía nada que ver con el metacampo real.