Практическая задача, когда требуется «спрятать» в конец списка публикации, для которых пока нет прикрепленного изображения. Это может быть архив или страница какой то рубрики, таксономии и т.п.
Лента таких страниц базируется на результате запроса через wp_query API. Последний фактически является набором фильтров, используемых для выборки публикации в wordpress.
В нашей задаче требуется сделать две вещи:
- присоединить таблицу мета полей публикаций с ключом ‘_thumbnail_id’,
- каким то образом использовать значение этого мета поля для сортировки.
Если с первой задачей API как то справляется, т.е. вы можете указать примерно следующее, чтобы произошел JOIN таблицы мета полей с не исключающими какие либо записи условиями:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
query_posts(array( 'meta_query' => array( 'relation' => 'OR', array( 'key' => '_thumbnail_id', 'value' => 0, 'compare' => '>', ), array( 'key' => '_thumbnail_id', 'value' => 'bug #23268', 'compare' => 'NOT EXISTS', ), ) )); |
то со вторым пунктом API не может вам помочь вовсе, т.к. набор допустимых ключей в фильтре orderby строго ограничен.
Да, несмотря на очень широкий ассортимент фильтров и постоянное развитие данного API, заменить собой SQL данное API не в состоянии. Поэтому для решения данной задачи придется использовать фильтры, чтобы вмешаться в создаваемый программой SQL запрос.
Начиная с версии WP 3.1.0 программисту доступен hook posts_clauses. Цель которого позволить изменить части выражения SQL на конечном этапе.
Добавим требуемые операции в функцию, которую будем цеплять через posts_clauses.
1 2 3 4 5 6 7 8 9 10 11 |
/** * Зацепка для wp_query, подключаемая по месту в нужных шаблонах */ function hook_posts_clauses($pieces) { // добавляем связку с трумбнейлами $pieces['join'] .= " LEFT JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id AND wp_postmeta.meta_key = '_thumbnail_id'"; // устанавливаем нужную сортировку $pieces['orderby'] = 'wp_postmeta.meta_value > 0 DESC, wp_posts.post_date DESC'; return $pieces; } |
Функцию можно объявить где то в functions.php, а подключать её следует точечно в нужных шаблонах через add_filter / remove_filter.
Вот как то так:
1 2 3 4 5 6 7 8 |
// подключаем зацепку-фильтр add_filter('posts_clauses', 'hook_posts_clauses'); // выполняем запрос через wp_query API query_posts(array( 'post_type' => 'article', )); // отключаем зацепку-фильтр, чтобы не повлиять на другие запросы remove_filter('posts_clauses', 'hook_posts_clauses'); |