Проблема заключается в том, что WordPress добавляет INNER JOIN
в таблицу wp_postmeta
, как только вы укажете meta_key
в ваших условиях. Один из способов обойти эту проблему, чтобы добавить фильтр на пункте order by
, что-то вроде этого:
function so_orderby_priority($original_orderby_statement) {
global $wpdb;
return "(SELECT $wpdb->postmeta.meta_value
FROM $wpdb->postmeta
WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id
AND $wpdb->postmeta.meta_key = 'priority') ASC";
}
add_filter('posts_orderby', 'so_orderby_priority');
query_posts(
array(
'tag' => $pagetag,
'paged' => get_query_var('paged')
)
);
remove_filter('posts_orderby', 'so_orderby_priority');
Примечание MySQL сортирует NULLs первый - если вы хотите, чтобы они отсортированы в прошлом, попробовать что-то вроде этого (предполагая, что все ваши приоритеты прийти до ZZZZZ по алфавиту):
function so_orderby_priority($original_orderby_statement) {
global $wpdb;
return "IFNULL(
(SELECT $wpdb->postmeta.meta_value
FROM $wpdb->postmeta
WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id
AND $wpdb->postmeta.meta_key = 'priority'),
'ZZZZZ') ASC";
}
Редактировать
Вот немного больше объяснение, которое предполагает, что вы понимаете SQL, по крайней мере немного.
Ваш оригинальный query_posts
в результате следующий запрос выполняется в базе данных:
SELECT wp_posts.*
FROM wp_posts
INNER JOIN wp_term_relationships ON (wp_posts.id = wp_term_relationships.object_id)
INNER JOIN wp_postmeta ON (wp_posts.id = wp_postmeta.post_id)
WHERE 1 = 1
AND (wp_term_relationships.term_taxonomy_id IN (3))
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private')
AND (wp_postmeta.meta_key = 'priority')
GROUP BY wp_posts.id
ORDER BY wp_postmeta.meta_value ASC
LIMIT 0, 10;
Это INNER JOIN wp_postmeta
то, что удалили все сообщения без приоритета от ваших результатов.
meta_*
Удаление связанных условий с вашей query_posts
:
query_posts(
array(
'tag' => $pagetag,
'paged' => get_query_var('paged')
)
);
решить эту проблему, но порядок сортировки по-прежнему не так. Новый SQL является
SELECT wp_posts.*
FROM wp_posts
INNER JOIN wp_term_relationships ON (wp_posts.id = wp_term_relationships.object_id)
WHERE 1 = 1
AND (wp_term_relationships.term_taxonomy_id IN (3))
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private')
GROUP BY wp_posts.id
ORDER BY wp_posts.post_date DESC
LIMIT 0, 10;
posts_orderby
фильтр позволяет изменять положение ORDER BY
: wp_posts.post_date DESC
заменяется на то, что возвращается фильтра. Окончательный SQL становится:
SELECT wp_posts.*
FROM wp_posts
INNER JOIN wp_term_relationships ON (wp_posts.id = wp_term_relationships.object_id)
WHERE 1 = 1
AND (wp_term_relationships.term_taxonomy_id IN (3))
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private')
GROUP BY wp_posts.id
ORDER BY (SELECT wp_postmeta.meta_value
FROM wp_postmeta
WHERE wp_posts.id = wp_postmeta.post_id
AND wp_postmeta.meta_key = 'priority') ASC
LIMIT 0, 10
, который делает то, что вам нужно.
Спасибо! Работал потрясающе ... хороший код ... Но я мог бы быть очень рад, если бы вы могли объяснить немного больше, что вы сделали. Im начинающий в php и на самом деле не полностью его понял ... Чем отличается от запроса функции к исходному запросу? И что конкретно сделал фильтр? – nimi
Рад, что это помогло. Решение больше MySQL, чем PHP, поскольку 'query_posts' генерирует SQL для работы с базой данных за кулисами. Фильтр полностью заменяет порядок сортировки в SQL кодом, который сортирует результаты так, как вам нужно. Я отредактирую свой ответ, чтобы добавить немного больше деталей. – Hobo
Спасибо! Отличный ответ и объяснение ... – nimi