Поиск пользовательского типа записей по метаданным

28 янв. 2014 г., 17:48:50
Просмотры: 19.6K
Голосов: 6

У меня есть пользовательский тип записи 'Property', который пользователи должны иметь возможность искать по метаданным.

У меня есть 3 функции поиска - 2 на фронтенде и 1 в админке - две из них работают как ожидалось, а одна вообще не фильтрует результаты.

Я думаю, проблема может быть либо в определении, либо в использовании пользовательских query_vars.

В моем functions.php у меня следующее:

function add_query_vars($public_query_vars) {
    $public_query_vars[] = 'bedrooms'; // спальни
    $public_query_vars[] = 'type';     // тип
    $public_query_vars[] = 'location'; // местоположение
    return $public_query_vars;
}
add_filter('query_vars', 'add_query_vars');

function meta_search_query($query) {

    $query_args_code = array(
      'posts_per_page' => 5,
      'post_type' => 'nc_property',
      'meta_key' => 'nc_code',
      'meta_value' => $query->query_vars['s'],
      'meta_compare' => 'LIKE'
    );


    $query_args_meta = array(
        'posts_per_page' => -1,
        'post_type' => 'nc_property',
        'meta_query' => array(
            'relation' => 'AND',
            array(
                'key' => 'nc_bedrooms',
                'value' => $query->query_vars['bedrooms'],
                'compare' => 'LIKE'
            ),
            array(
                'key' => 'nc_type',
                'value' => $query->query_vars['type'],
                'compare' => 'LIKE'
            ),
            array(
                'key' => 'nc_location',
                'value' => $query->query_vars['location'],
                'compare' => 'LIKE'
            )
        )
    );

    if (is_admin() && $query->is_search ) {
        query_posts($query_args_code);

    } elseif (!is_admin() && $query->is_search ) {
        if ($_REQUEST["which_form"] == 'meta_form') {
            query_posts($query_args_meta);

        } elseif ($_REQUEST["which_form"] == 'code_form'){
            query_posts($query_args_code);

        }
    }  
}
add_filter( 'pre_get_posts', 'meta_search_query');

Поиск по коду свойства работает без проблем как на фронтенде, так и в админке. Однако попытки фильтровать результаты по пользовательским query_vars - location, type и bedrooms - каждый раз терпят неудачу.

Пример строки запроса, которая создается:

/property/?post_type=nc_property&which_form=meta_form&bedrooms=Two&type=Apartment&location=Bahceli

На сайте есть одно свойство, соответствующее этим параметрам, но WordPress каждый раз возвращает все результаты.

Может я что-то упустил?

РЕДАКТИРОВАНИЕ: Оказалось, что поскольку моя форма поиска для мета-запросов не использовала элемент с именем 's', условие $query->is_search в моем операторе if возвращало false, что означало, что мой meta_query просто не вызывался.

Спасибо fischi за то, что заметил это для меня! :D

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

Распознаются ли пользовательские query vars в WordPress? Если выполнить var_dump, получаете ли вы значения в $query->query_vars?

fischi fischi
28 янв. 2014 г. 18:10:28

Хм, все пользовательские query vars возвращают NULL при var dump. Почему так происходит?

Jazibobs Jazibobs
28 янв. 2014 г. 18:16:11

Вероятно, из-за смешения красивых постоянных ссылок и переменных $_GET. Можете попробовать вставить данные из $_GET вместо $query->query_vars? Не забудьте их санитизировать, если пойдёте этим путём :)

fischi fischi
28 янв. 2014 г. 18:18:59

использование $_GET возвращает переменные как ожидалось: array(3) { [0]=> string(3) "Two" [1]=> string(9) "Apartment" [2]=> string(7) "Bahceli" } как думаешь, простое замена на $_GET в моем functions.php решит проблему?

Jazibobs Jazibobs
28 янв. 2014 г. 18:29:43

Это отвечает на твой вопрос? Использование get_posts с аргументами, найденными в meta keys

T.Todua T.Todua
30 янв. 2021 г. 19:09:51
Все ответы на вопрос 1
6

В данном случае, так как вы совмещаете красивые постоянные ссылки с параметрами запроса, я бы использовал переменные $_GET в вашем запросе.

$query_args_meta = array(
    'posts_per_page' => -1,
    'post_type' => 'nc_property',
    'meta_query' => array(
        'relation' => 'AND',
        array(
            'key' => 'nc_bedrooms',
            'value' => sanitize_text_field( $_GET['bedrooms'] ),
            'compare' => 'LIKE'
        ),
        array(
            'key' => 'nc_type',
            'value' => sanitize_text_field( $_GET['type'] ),
            'compare' => 'LIKE'
        ),
        array(
            'key' => 'nc_location',
            'value' => sanitize_text_field( $_GET['location'] ),
            'compare' => 'LIKE'
        )
    )
);

Обязательно используйте правильную санацию в зависимости от ваших потребностей или функцию, которая проверяет разрешенные значения данных $_GET.

Также проверьте ваши условные функции — изменяйте запрос только если это поисковый запрос (используя параметр s для поиска) или измените оператор if.

28 янв. 2014 г. 18:35:31
Комментарии

Я внес рекомендованные изменения, однако результаты поиска по-прежнему не фильтруются, хотя я знаю, что переменные $_GET корректно определяются, когда я делаю var_dump...

Jazibobs Jazibobs
28 янв. 2014 г. 18:38:13

Можешь посмотреть, какой запрос выполняет твой WordPress? <?php echo $GLOBALS['wp_query']->request; ?>

fischi fischi
28 янв. 2014 г. 18:42:07

Запрос выглядит следующим образом: SELECT SQL_CALC_FOUND_ROWS north_posts.ID FROM north_posts WHERE 1=1 AND north_posts.post_type = 'nc_property' AND (north_posts.post_status = 'publish' OR north_posts.post_status = 'private') ORDER BY north_posts.post_date DESC LIMIT 0, 10

Похоже, что мой meta-query просто игнорируется? :/

Jazibobs Jazibobs
28 янв. 2014 г. 18:45:28

упс, заметил ещё кое-что - если вы не используете параметр s, ваше условие if (!is_admin() && $query->is_search ) не выполняется, так как WordPress не понимает, что это поиск. Попробуйте изменить и это.

fischi fischi
28 янв. 2014 г. 19:03:40

Вы герой WordPress! То, что одно из полей поиска получило имя 's', решило проблему!

Jazibobs Jazibobs
28 янв. 2014 г. 19:14:14

Отлично. Я обновил ответ :)

fischi fischi
28 янв. 2014 г. 19:16:24
Показать остальные 1 комментариев