Фильтрация по одному произвольному полю и сортировка по другому

17 февр. 2011 г., 16:19:15
Просмотры: 20.3K
Голосов: 11

У меня есть произвольный тип записи "Listing" и я хочу получить все записи, у которых произвольное поле gateway_value != 'Yes', и отсортировать результаты по другому произвольному полю location_level1_value. Запросы работают по отдельности, но я не могу их объединить:

Запрос 1 (сортировка по местоположению):

                $wp_query = new WP_Query( array (
                    'post_type' => 'listing',
                    'post_status' => 'publish',
                    'posts_per_page' => '9',
                    'meta_key' => 'location_level1_value',
                    'orderby' => 'location_level1_value',
                    'order' => 'ASC',
                    'paged' => $paged
                    )
                 );

Запрос 2 (значение произвольного поля != Yes):

                $wp_query = new WP_Query( array (
                    'post_type' => 'listing',
                    'posts_per_page' => '9',
                    'post_status' => 'publish',
                    'meta_key' => 'gateway_value',
                    'meta_value' => 'Yes',
                    'meta_compare' => '!=',
                    'paged' => $paged
                    )
                );

Объединенный запрос:

Я посмотрел документацию для помощи с этим, но следующий запрос не работает:

                $wp_query = new WP_Query( array (
                    'post_type' => 'listing',
                    'posts_per_page' => '9',
                    'post_status' => 'publish',
                    'meta_query' => array(
                        array(
                            'key' => 'gateway_value',
                            'value' => 'Yes',
                            'compare' => '!='
                        ),
                        array(
                            'key' => 'location_level1_value'
                        )
                    ),
                    'orderby' => "location_level1_value",
                    'order' => 'ASC',
                    'paged' => $paged
                    )
                );

Что я делаю неправильно в объединенном запросе?

[ОБНОВЛЕНИЕ]: После выхода версии 3.1, объединенный запрос выше все еще не работает. Я получаю результаты, но они неправильно отсортированы.

[ОБНОВЛЕНИЕ]: var_dump($wp_query->request) выдает следующее:
string(527) " SELECT SQL_CALC_FOUND_ROWS wp_7v1oev_posts.* FROM wp_7v1oev_posts INNER JOIN wp_7v1oev_postmeta ON (wp_7v1oev_posts.ID = wp_7v1oev_postmeta.post_id) INNER JOIN wp_7v1oev_postmeta AS mt1 ON (wp_7v1oev_posts.ID = mt1.post_id) WHERE 1=1 AND wp_7v1oev_posts.post_type = 'listing' AND (wp_7v1oev_posts.post_status = 'publish') AND wp_7v1oev_postmeta.meta_key = 'gateway_value' AND CAST(wp_7v1oev_postmeta.meta_value AS CHAR) != 'Yes' AND mt1.meta_key = 'location_level1_value' ORDER BY wp_7v1oev_posts.post_date DESC LIMIT 0, 9"

3
Комментарии

Вы используете WordPress 3.1? Параметр meta_query появился только в версии 3.1, которая скоро выйдет, но текущая стабильная версия всё ещё 3.0.5, и в ней этого параметра нет.

Jan Fabry Jan Fabry
17 февр. 2011 г. 17:08:25

Э-э... понятно, вероятно, поэтому оно и не работает. Есть ли способ заставить это работать в 3.0.5?

gillespieza gillespieza
17 февр. 2011 г. 18:11:25

У Miljenko лучший ответ, вам следует принять его вместо вашего.

Hugo Hugo
3 апр. 2012 г. 08:24:38
Все ответы на вопрос 3
0

Вы можете использовать запрос для фильтрации контента, как задумано, с помощью 'meta_query' и параметров фильтрации. Для сортировки просто добавьте/измените следующие параметры:

  • 'orderby' => 'meta_value'
  • 'meta_key' => 'location_level1_value'
  • 'order' => 'ASC'

    $wp_query = new WP_Query( array (
        'post_type'      => 'listing',
        'posts_per_page' => '9',
        'post_status'    => 'publish',
        'meta_query'     => array(
            array(
                'key'       => 'gateway_value',
                'value'     => 'Yes',
                'compare'   => '!='
            )
        ),
        'orderby'  => 'meta_value',            // это означает, что мы будем использовать выбранное 
                                               // мета-поле для сортировки
    
        'meta_key' => 'location_level1_value', // здесь указывается, какое мета-поле 
                                               // будет использоваться для сортировки, 
                                               // независимо от фильтров
        'order'    => 'ASC',
        'paged'    => $paged
        )
    );
    
14 окт. 2011 г. 00:39:00
11

Как уже сказал Jan, в новой WordPress 3.1 можно использовать meta_query, но пока эта версия не вышла, вы можете использовать ваш первый запрос для сортировки (orderby) и фильтрации внутри вашего цикла, вот так:

Global $my_query;
$my_query = new WP_Query( array (
                    'post_type' => 'listing',
                    'post_status' => 'publish',
                    'posts_per_page' => '9',
                    'meta_key' => 'location_level1_value',
                    'orderby' => 'location_level1_value',
                    'order' => 'ASC',
                    'paged' => $paged
                    )
                 );
while ($my_query->have_posts){
    $my_query->the_post();
              //делаем нужные операции в цикле
} 

и добавить этот код в ваш файл functions.php

   //фильтр join
         add_filter('posts_join', 'listing_join_865' );
         function listing_join_865($join){
Global$ my_query;            
if ('listing' = $my_query->query['post_type']){
                $restriction1 = 'gateway_value';
                return $join .="
                LEFT JOIN $wpdb->postmeta AS $restriction1 ON(
                $wpdb->posts.ID = $restriction1.post_id
                AND $restriction1.meta_key = '$restriction1'
                )";
             }else {
                return $join;
            }
         }
         //фильтр where
         add_filter('posts_where', 'listing_where_865' );
         function listing_where_865($where){
             global $my_query;
            if ('listing' = $my_query->query['post_type']){
                return $where.= " AND $restriction1.meta_value != 'yes'";
            }else{
                return $where;
            }
         }

Теперь это должно работать.

17 февр. 2011 г. 18:12:57
Комментарии

Спасибо за это. Это работает, за исключением странного побочного эффекта - моя пагинация перестала работать правильно. Вместо 9 элементов на странице, в моей сетке появляются "пустые места", где должны были быть кастомные записи с gateway_value == "Yes", если бы не было условия... Есть идеи как это исправить?

gillespieza gillespieza
17 февр. 2011 г. 18:53:40

да, это сломает пагинацию, так что единственный выход - кастомный sql запрос, дай мне пару минут.

Bainternet Bainternet
17 февр. 2011 г. 19:10:27

Не беспокойся - я просто воспользуюсь вторым запросом и плагином http://wordpress.org/extend/plugins/post-types-order до выхода версии 3.1 :)

gillespieza gillespieza
17 февр. 2011 г. 19:20:55

черт, я только что вернулся и увидел ваш комментарий, уже найдя решение. в любом случае, оно здесь для будущих спрашивающих.

Bainternet Bainternet
17 февр. 2011 г. 20:01:31

@בניית אתרים - Если вы сделаете отступы во всём своём коде, его будет проще вставлять в ответы. Например: Поместите код в ваш редактор, выделите всё, затем сделайте отступ один раз, теперь скопируйте и вставьте — и вам не нужно будет добавлять по 4 пробела перед каждой строкой кода (весь код красиво поместится в блок кода без лишних манипуляций).

t31os t31os
17 февр. 2011 г. 20:18:37

@t31os - я обычно так и делаю, но не когда отвечаю с телефона.

Bainternet Bainternet
17 февр. 2011 г. 20:20:38

Ты написал это с телефона... уважаю!.. Я бы даже не попытался писать код на телефоне.. :) +1 за скиллы на телефоне! ;)

t31os t31os
17 февр. 2011 г. 20:39:09

t31os: LOL , HTC desire рулит!!

Bainternet Bainternet
17 февр. 2011 г. 20:40:23

Я пробовал вставлять блоки кода с табами из моего текстового редактора, но это никогда не работает - мне всегда приходится добавлять пробелы вручную

gillespieza gillespieza
17 февр. 2011 г. 23:07:48

Копирование и вставка из Notepad++ в Firefox работает нормально.

Bainternet Bainternet
17 февр. 2011 г. 23:11:27

Попробую это (сейчас использую PsPad и Chrome)

gillespieza gillespieza
19 февр. 2011 г. 20:37:23
Показать остальные 6 комментариев
0

Apologies for answering my own question:

Looking at [http://core.trac.wordpress.org/ticket/15031][1], seems like this is a known issue. I have fixed (hacked?) it to work using post_filter, like so (just for anyone's reference who might be searching for the same answer):

In functions.php###

add_filter('posts_orderby', 'EV_locationl1' );
function EV_locationl1 ($orderby) {
    global $EV_locationl1_orderby;
    if ($EV_locationl1_orderby) $orderby = $EV_locationl1_orderby;
    return $orderby;
}

Amended wp_query in template file###

$EV_locationl1_orderby = " mt1.meta_value ASC";

$wp_query = new WP_Query( array (
    'post_type' => 'listing',
    'posts_per_page' => '9',
    'post_status' => 'publish',
    'meta_query' => array(
            array(
                    'key' => 'gateway_value',
                    'value' => 'Yes',
                    'compare' => '!='
                    ),
            array(
                    'key' => 'location_level1_value'
            )
        ),
    'order' => $EV_locationl1_orderby,
    'paged' => $paged
    ));
24 февр. 2011 г. 00:38:17