Создание формы поиска для произвольных полей

15 окт. 2014 г., 15:49:24
Просмотры: 62K
Голосов: 13

Я разработал тему для автосалона. Каждый автомобиль представлен как произвольный тип записи ("vehicle") и имеет около 12 произвольных полей, таких как Марка, Модель, Пробег, Тип топлива и т.д.

В общем, на главной странице я хочу создать форму поиска с выпадающими списками для Марки и Модели, которые содержат все доступные марки и модели.

Также я хочу добавить 2 поля для Года, чтобы пользователь мог выбрать "2006" и "2012", а результаты поиска показывали все автомобили, год выпуска которых находится между этими двумя значениями.

Существует ли плагин, который может это реализовать?

Спасибо за любую помощь... я уже несколько часов ломаю над этим голову!!!!

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

Думаю, вам может помочь этот плагин: https://wordpress.org/plugins/wp-custom-fields-search/

DINESH BHIMANI DINESH BHIMANI
15 окт. 2014 г. 16:00:28

Спасибо... Но это не объясняет, как фактически создать форму поиска. Я могу запрограммировать форму в HTML, но как заставить её реально работать?!

absdigital absdigital
15 окт. 2014 г. 16:41:10
Все ответы на вопрос 2
2
27

Хотя ответ @MayeenulIslam может работать, я считаю, что правильный способ реализации расширенного поиска - это использование хука действия pre_get_posts.

Шаг 1: Форма поиска

Этот шаг аналогичен шагу 1 в другом ответе, просто изменен id поля name (<input type="text" ...>), используемого для поиска, на "s", чтобы оно использовалось напрямую как поле поиска. Сохраните этот код в advanced-searchform.php в папке вашей темы. Затем используйте get_template_part( 'advanced', 'searchform' ); для загрузки формы там, где вам нужно:

<?php /**`advanced-searchform.php`*/ ?>
<form method="get" id="advanced-searchform" role="search" action="<?php echo esc_url( home_url( '/' ) ); ?>">

    <h3><?php _e( 'Расширенный поиск', 'textdomain' ); ?></h3>

    <!-- ЭТО ПЕРЕДАЕТСЯ ДЛЯ АКТИВАЦИИ СТРАНИЦЫ РЕЗУЛЬТАТОВ РАСШИРЕННОГО ПОИСКА ИЗ functions.php -->
    <input type="hidden" name="search" value="advanced">

    <label for="s" class=""><?php _e( 'Название: ', 'textdomain' ); ?></label><br>
    <input type="text" value="" placeholder="<?php _e( 'Введите название автомобиля', 'textdomain' ); ?>" name="s" id="name" />

    <label for="model" class=""><?php _e( 'Выберите модель: ', 'textdomain' ); ?></label><br>
    <select name="model" id="model">
        <option value=""><?php _e( 'Выберите...', 'textdomain' ); ?></option>
        <option value="model1"><?php _e( 'Модель 1', 'textdomain' ); ?></option>
        <option value="model2"><?php _e( 'Модель 2', 'textdomain' ); ?></option>
    </select>

    <input type="submit" id="searchsubmit" value="Поиск" />

</form>

Шаг 2: Добавление фильтров к поисковому запросу

add_action( 'pre_get_posts', 'advanced_search_query' );
function advanced_search_query( $query ) {

    if ( isset( $_REQUEST['search'] ) && $_REQUEST['search'] == 'advanced' && ! is_admin() && $query->is_search && $query->is_main_query() ) {

        $query->set( 'post_type', 'vehicle' );

        $_model = $_GET['model'] != '' ? $_GET['model'] : '';

        $meta_query = array(
                            array(
                                'key'     => 'car_model', // предполагается, что ваш meta_key это 'car_model'
                                'value'   => $_model,
                                'compare' => 'LIKE', // находит модели, соответствующие 'model' из выпадающего списка
                            )
                        )
        );
        $query->set( 'meta_query', $meta_query );

    }
}

Шаг 3: Шаблонизация (опционально)

При таком подходе будет использоваться стандартный шаблон поиска WordPress с фильтрацией результатов без необходимости дополнительного запроса. Если вы хотите использовать другой шаблон для расширенного поиска, вы можете использовать фильтр template_include. Например, если вы хотите использовать файл advanced-search-template.php в качестве шаблона для результатов расширенного поиска:

add_action('template_include', 'advanced_search_template');
function advanced_search_template( $template ) {
  if ( isset( $_REQUEST['search'] ) && $_REQUEST['search'] == 'advanced' && is_search() ) {
     $t = locate_template('advanced-search-template.php');
     if ( ! empty($t) ) {
         $template = $t;
     }
  }
  return $template;
}
2 февр. 2015 г. 12:04:16
Комментарии

Большое спасибо за WordPress-способ. Только что поработал с ним, и это потрясающе. :)

Mayeenul Islam Mayeenul Islam
30 апр. 2015 г. 20:39:20

Спасибо. Это помогло.

Abdul Samad Abdul Samad
5 авг. 2021 г. 15:55:04
5
17

______ОБНОВЛЕНИЕ_______
Хотя я получаю все больше голосов, и решение работает, но ответ cybmeta на самом деле является правильным и соответствует методологии WordPress. Вам определенно стоит попробовать этот вариант.

Шаг 1

Начните с создания расширенной формы поиска, с которой будет взаимодействовать пользователь, и сохраните ее под определенным именем (например, я сохранил как advanced-searchform.php — но не сохраняйте как searchform.php, иначе она заменит стандартную форму поиска WordPress):

<form method="get" id="advanced-searchform" role="search" action="<?php echo esc_url( home_url( '/' ) ); ?>">

    <h3><?php _e( 'Расширенный поиск', 'textdomain' ); ?></h3>

    <!-- ЭТОТ ПАРАМЕТР ЗАПУСКАЕТ СТРАНИЦУ РЕЗУЛЬТАТОВ РАСШИРЕННОГО ПОИСКА ИЗ functions.php -->
    <input type="hidden" name="search" value="advanced">

    <label for="name" class=""><?php _e( 'Название: ', 'textdomain' ); ?></label><br>
    <input type="text" value="" placeholder="<?php _e( 'Введите название автомобиля', 'textdomain' ); ?>" name="name" id="name" />

    <label for="model" class=""><?php _e( 'Выберите модель: ', 'textdomain' ); ?></label><br>
    <select name="model" id="model">
        <option value=""><?php _e( 'Выберите...', 'textdomain' ); ?></option>
        <option value="model1"><?php _e( 'Модель 1', 'textdomain' ); ?></option>
        <option value="model2"><?php _e( 'Модель 2', 'textdomain' ); ?></option>
    </select>

    <input type="submit" id="searchsubmit" value="Поиск" />

</form>

Затем вызовите форму в вашем шаблоне следующим образом:

<?php get_template_part( 'advanced', 'searchform' ); ?>

Теперь ваша форма поиска готова, и вы можете использовать ее для получения пользовательского ввода через URL.

Шаг 2

Теперь вам нужно: выполнить запрос к базе данных и проверить записи и их произвольные поля согласно поисковому запросу. Помните, что ваш поисковый запрос теперь находится в URL после отправки формы. Скажите WordPress загружать вашу собственную страницу результатов поиска при отправке формы. Добавьте следующую функцию в ваш functions.php, чтобы она использовала ваш шаблон вместо стандартного search.php:

<?php
function wpse_load_custom_search_template(){
    if( isset($_REQUEST['search']) == 'advanced' ) {
        require('advanced-search-result.php');
        die();
    }
}
add_action('init','wpse_load_custom_search_template');
?>

Я нашел этот код где-то на WPSE (забыл источник), но есть споры по поводу его использования. Однако он работает (хотя это слабое оправдание).

Проверьте альтернативный способ, предложенный @G.M.

Шаг 3

Создайте новый файл и сохраните его как advanced-search-result.php (потому что мы использовали это имя в functions.php), и теперь вы свободны. Концепция такова:

  • Получите данные из URL,
  • Используйте простой WP_Query() (если ваш запрос сложный, используйте $wpdb),
  • Передайте параметры в запрос, получите данные из базы,
  • Покажите результат[ы]

Пример может быть таким:

<?php
// Получаем данные из URL в переменные
$_name = $_GET['name'] != '' ? $_GET['name'] : '';
$_model = $_GET['model'] != '' ? $_GET['model'] : '';

// Формируем запрос
$v_args = array(
        'post_type'     =>  'vehicle', // ваш CPT
        's'             =>  $_name, // ищет по ключевому слову из поля 'name'
        'meta_query'    =>  array(
                                array(
                                    'key'     => 'car_model', // предполагается, что ваш meta_key — 'car_model'
                                    'value'   => $_model,
                                    'compare' => 'LIKE', // ищет модели, совпадающие с выбранной в поле
                                ),
                            )
    );
$vehicleSearchQuery = new WP_Query( $v_args );

// Раскомментируйте для отладки запроса
// var_dump($vehicleSearchQuery->request);

// Показываем результаты
if( $vehicleSearchQuery->have_posts() ) :
    while( $vehicleSearchQuery->have_posts() ) : $vehicleSearchQuery->the_post();
        the_title(); // Предполагается, что названия авто — это заголовки записей CPT
    endwhile;
else :
    _e( 'Извините, ничего не найдено по вашему запросу', 'textdomain' );
endif;
wp_reset_postdata();
?>

Итак, вот ваш окончательный вариант. Однако остаются некоторые сложности:

  • Альтернативные значения — расширенный поиск может выполняться по ВСЕМ полям или ЛЮБОМУ из них, поэтому убедитесь, что запрос учитывает все параметры поиска. Для сложных запросов можно использовать $wpdb и чистый SQL — здесь WordPress уже не участвует.
  • Санитизация и валидация — текстовые поля уязвимы и могут нанести вред вашему сайту. Передавайте только проверенные данные. (Санитизация и валидация данных в WordPress - TutsPlus)
  • Дизайн — вы можете использовать шаблон page.php (или search.php) для оформления этой страницы.

Итак, вы поняли идею, теперь ваша очередь исследовать и находить свой путь. Помните, у каждого свой путь. Создайте свой, чтобы мне было у кого учиться. :)

15 окт. 2014 г. 18:45:35
Комментарии

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

absdigital absdigital
15 окт. 2014 г. 19:00:54

Буду рад, если это сработает для вас. :)

Mayeenul Islam Mayeenul Islam
15 окт. 2014 г. 19:01:42

Вы не знаете, как сделать так, чтобы выпадающее меню "Марки" автоматически отображало все марки, которые были введены в одном из постов о транспортных средствах?

absdigital absdigital
15 окт. 2014 г. 19:06:19

используйте WP_Query() с параметрами произвольных полей и организуйте цикл для вывода элементов <option>.

Mayeenul Islam Mayeenul Islam
15 окт. 2014 г. 19:06:22

Я бы хотел увидеть этот "расширенный поиск" реализованным с использованием хука pre_get_posts, а не через дополнительный цикл.

cybmeta cybmeta
2 февр. 2015 г. 11:44:01