Как сортировать селект по цену, по рейтингу, по стажу?
<form action="<?php echo esc_url($_SERVER['REQUEST_URI']); ?>" method="POST" id="filter"> <select class="form-select" aria-label="Default select example" name="sort"> <option selected>Сортировать</option> <option value="review">по отзывам</option> <option value="price_sort">по цене</option> <option value="rating">по рейтингу</option> <option value="exp">по стажу</option> </select> <button>Применить фильтр</button><input type="hidden" name="action" value="myfilter"> </form> |
<form action="<?php echo esc_url($_SERVER['REQUEST_URI']); ?>" method="POST" id="filter"> <select class="form-select" aria-label="Default select example" name="sort"> <option selected>Сортировать</option> <option value="review">по отзывам</option> <option value="price_sort">по цене</option> <option value="rating">по рейтингу</option> <option value="exp">по стажу</option> </select> <button>Применить фильтр</button><input type="hidden" name="action" value="myfilter"> </form>
Вот есть форма, не могу сортировать записи по цену например.
По отзывам получилось сортировать, но другие поля никак не могу
Вот кусок кода, где вывожу посты:
<div class="row justify-content-center"> <?php $current_page = (get_query_var('paged')) ? get_query_var('paged') : 1; query_posts(array('post_per_page' => 10, 'post_type' => 'page', 'post_parent' => 65, 'orderby' => 'meta_value', 'meta_key' => 'exp', 'order' => 'ASC', 'paged' => $current_page)); $wp_query->is_archive = true; $wp_query->is_home = false; $count = 0; while (have_posts()): the_post(); ?> <?php $count++; ?> <div class="col-9"> <div class="cards bg-white rounded-3 mb-4 border-0 p-3 p-lg-4" id="result"> <div class="row"> <div class="col-12 col-md-2 text-center"> |
<div class="row justify-content-center"> <?php $current_page = (get_query_var('paged')) ? get_query_var('paged') : 1; query_posts(array('post_per_page' => 10, 'post_type' => 'page', 'post_parent' => 65, 'orderby' => 'meta_value', 'meta_key' => 'exp', 'order' => 'ASC', 'paged' => $current_page)); $wp_query->is_archive = true; $wp_query->is_home = false; $count = 0; while (have_posts()): the_post(); ?> <?php $count++; ?> <div class="col-9"> <div class="cards bg-white rounded-3 mb-4 border-0 p-3 p-lg-4" id="result"> <div class="row"> <div class="col-12 col-md-2 text-center">
В functions.php написал так, не работает
add_action('wp_enqueue_scripts', 'truemisha_jquery_scripts'); function truemisha_jquery_scripts() { wp_enqueue_script('jquery'); wp_register_script('filter', get_stylesheet_directory_uri() . '/js/filter.js', array('jquery'), time(), true); wp_enqueue_script('filter'); } wp_localize_script('filter', 'true_obj', array('ajaxurl' => admin_url('admin-ajax.php'))); add_action('wp_ajax_myfilter', 'myfilter_callback'); add_action('wp_ajax_nopriv_myfilter', 'myfilter_callback'); // Обработка формы фильтрации function handle_filter_form() { if (isset($_POST['sort']) && $_POST['sort'] === 'review') { add_filter('posts_orderby', 'sort_by_reviews_count'); } } add_action('pre_get_posts', 'handle_filter_form'); // Сортировка по количеству отзывов function sort_by_reviews_count($orderby) { global $wpdb; $orderby = "(SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = $wpdb->posts.ID) DESC"; return $orderby; } function custom_price_sort($query) { if (is_admin() || !$query->is_main_query()) { return; } if (isset($_POST['sort']) && $_POST['sort'] === 'price_sort') { $query->set('orderby', 'meta_value'); // Сортировка по количеству отзывов $query->set('meta_key', 'price_sort'); // По убыванию (от большего к меньшему) } } add_action('pre_get_posts', 'custom_price_sort'); |
add_action('wp_enqueue_scripts', 'truemisha_jquery_scripts'); function truemisha_jquery_scripts() { wp_enqueue_script('jquery'); wp_register_script('filter', get_stylesheet_directory_uri() . '/js/filter.js', array('jquery'), time(), true); wp_enqueue_script('filter'); } wp_localize_script('filter', 'true_obj', array('ajaxurl' => admin_url('admin-ajax.php'))); add_action('wp_ajax_myfilter', 'myfilter_callback'); add_action('wp_ajax_nopriv_myfilter', 'myfilter_callback'); // Обработка формы фильтрации function handle_filter_form() { if (isset($_POST['sort']) && $_POST['sort'] === 'review') { add_filter('posts_orderby', 'sort_by_reviews_count'); } } add_action('pre_get_posts', 'handle_filter_form'); // Сортировка по количеству отзывов function sort_by_reviews_count($orderby) { global $wpdb; $orderby = "(SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = $wpdb->posts.ID) DESC"; return $orderby; } function custom_price_sort($query) { if (is_admin() || !$query->is_main_query()) { return; } if (isset($_POST['sort']) && $_POST['sort'] === 'price_sort') { $query->set('orderby', 'meta_value'); // Сортировка по количеству отзывов $query->set('meta_key', 'price_sort'); // По убыванию (от большего к меньшему) } } add_action('pre_get_posts', 'custom_price_sort');
Еще попробовал так, тоже не помогает
// Добавляем обработчик AJAX-запроса для сортировки продуктов function myfilter_callback() { $sort = $_POST['sort']; // Получаем значение сортировки из AJAX-запроса $args = array( 'post_type' => 'page', // Укажи тип поста для продуктов 'posts_per_page' => -1, // Укажи количество продуктов, которые нужно вывести (-1 для вывода всех) 'meta_key' => 'price_sort', // Укажи поле метаданных ACF для цены 'orderby' => 'meta_value_num', // Укажи тип сортировки по числовому значению 'order' => 'ASC' // Укажи порядок сортировки в зависимости от выбранного значения ); $query = new WP_Query($args); if ($query->have_posts()) { while ($query->have_posts()) { $query->the_post(); // Вывод продукта the_title(); // Название продукта the_field('price_sort'); // Цена продукта } wp_reset_postdata(); } else { // Если продукты не найдены echo 'Продукты не найдены.'; } die(); } |
// Добавляем обработчик AJAX-запроса для сортировки продуктов function myfilter_callback() { $sort = $_POST['sort']; // Получаем значение сортировки из AJAX-запроса $args = array( 'post_type' => 'page', // Укажи тип поста для продуктов 'posts_per_page' => -1, // Укажи количество продуктов, которые нужно вывести (-1 для вывода всех) 'meta_key' => 'price_sort', // Укажи поле метаданных ACF для цены 'orderby' => 'meta_value_num', // Укажи тип сортировки по числовому значению 'order' => 'ASC' // Укажи порядок сортировки в зависимости от выбранного значения ); $query = new WP_Query($args); if ($query->have_posts()) { while ($query->have_posts()) { $query->the_post(); // Вывод продукта the_title(); // Название продукта the_field('price_sort'); // Цена продукта } wp_reset_postdata(); } else { // Если продукты не найдены echo 'Продукты не найдены.'; } die(); }
Ну вот и сам жс
// jQuery(function ($) { // $('#filter').submit(function () { // var filter = $(this); // $.ajax({ // url: true_obj.ajaxurl, // обработчик // data: filter.serialize(), // данные // type: 'POST', // тип запроса // beforeSend: function (xhr) { // filter.find('button').text('Загружаю...'); // изменяем текст кнопки // }, // success: function (data) { // filter.find('button').text('Применить фильтр'); // возвращаеи текст кнопки // $('#response').html(data); // } // }); // return false; // }); // console.log(filter); // console.log("aaaaa"); // }); jQuery(function ($) { // При изменении значения выпадающего списка $('#filter select').change(function () { var sort = $(this).val(); // Получаем выбранное значение console.log(sort); // Отправляем AJAX-запрос $.ajax({ url: '<?php echo admin_url("admin-ajax.php"); ?', // URL-адрес обработчика AJAX-запроса type: 'POST', data: { action: 'myfilter', // Имя действия, которое будет использовано на сервере sort: sort // Передаем выбранное значение сортировки }, beforeSend: function () { // Показываем прелоадер или другой индикатор загрузки }, success: function (response) { // Обновляем содержимое страницы с результатами сортировки $('#result').html(response); }, error: function (xhr, ajaxOptions, thrownError) { // Обрабатываем ошибку, если она возникла } }); return false; }); }); |
// jQuery(function ($) { // $('#filter').submit(function () { // var filter = $(this); // $.ajax({ // url: true_obj.ajaxurl, // обработчик // data: filter.serialize(), // данные // type: 'POST', // тип запроса // beforeSend: function (xhr) { // filter.find('button').text('Загружаю...'); // изменяем текст кнопки // }, // success: function (data) { // filter.find('button').text('Применить фильтр'); // возвращаеи текст кнопки // $('#response').html(data); // } // }); // return false; // }); // console.log(filter); // console.log("aaaaa"); // }); jQuery(function ($) { // При изменении значения выпадающего списка $('#filter select').change(function () { var sort = $(this).val(); // Получаем выбранное значение console.log(sort); // Отправляем AJAX-запрос $.ajax({ url: '<?php echo admin_url("admin-ajax.php"); ?', // URL-адрес обработчика AJAX-запроса type: 'POST', data: { action: 'myfilter', // Имя действия, которое будет использовано на сервере sort: sort // Передаем выбранное значение сортировки }, beforeSend: function () { // Показываем прелоадер или другой индикатор загрузки }, success: function (response) { // Обновляем содержимое страницы с результатами сортировки $('#result').html(response); }, error: function (xhr, ajaxOptions, thrownError) { // Обрабатываем ошибку, если она возникла } }); return false; }); });
Простите, что так много кода, просто не знал как по другому объяснить)
Дополнительно:
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Сортировку селекта «по цене, рейтингу, стажу» нужно делать по данным, а не по тексту option. Если значения приходят из массива объектов, проще отсортировать массив перед выводом. Если селект уже отрендерен в HTML, можно сортировать options на JavaScript, но это хуже для доступности и повторного использования.
Пример на PHP, если данные хранятся массивом:
$items = [ ['title' => 'Иван', 'price' => 3000, 'rating' => 4.8, 'experience' => 5], ['title' => 'Пётр', 'price' => 2500, 'rating' => 4.6, 'experience' => 8], ]; $sort = $_GET['sort'] ?? 'price'; usort($items, function ($a, $b) use ($sort) { return match ($sort) { 'rating' => $b['rating'] $a['rating'], 'experience' => $b['experience'] $a['experience'], default => $a['price'] $b['price'], }; }); echo '<select name="master">'; foreach ($items as $item) { echo '<option>' . esc_html($item['title']) . '</option>'; } echo '</select>';
Если это WordPress-записи, храните цену, рейтинг и стаж в числовых meta fields и сортируйте через
WP_Query:$query = new WP_Query([ 'post_type' => 'master', 'meta_key' => 'price', 'orderby' => 'meta_value_num', 'order' => 'ASC', ]);
Для разных сортировок меняйте
meta_keyиorderпо белому списку. Нельзя напрямую подставлять$_GET['sort']в параметры запроса без проверки.Если нужен выбор пользователем, делайте отдельный селект сортировки и перезагружайте список через GET или AJAX. Но исходные данные всё равно должны иметь отдельные числовые поля, иначе сортировка строк даст ошибки вроде
10000раньше900.Перед внедрением на рабочем сайте проверьте решение на копии или хотя бы сделайте резервную копию изменяемого файла. После правки включите отображение ошибок, откройте проблемную страницу в обычном и приватном окне, проверьте консоль браузера и логи PHP. Если задача связана с WordPress, WooCommerce или ACF, дополнительно проверьте поведение после очистки кэша и после выхода из админки: часть ошибок видна только для незалогиненного пользователя.
Если код работает только в одном шаблоне, лучше не оставлять его разрозненно в нескольких файлах. Вынесите повторяемую логику в функцию, небольшой плагин или template part, а в шаблоне оставьте только вызов. Так проще поддерживать решение после обновления темы, плагинов и PHP.