Добавляем свои варианты сортировки в woocommerce, кроме стандартных: по цене, по новизне, по популярности, по рейтингам.
Сортировке поддаются только числовые свойства товаров содержащихся у каждого товара. Сортировка по атрибуту относится к фильтрации. По этой причине пропала возможность с версии WC 3.0 сортировать по рекомендуемым (featured) товарам, т.к. эта особенность стала содержаться не в meta а в дополнительной таксономии product_visibility.
В Woocommerce заложена возможность произвольной сортировки товаров и категорий.
Вариант сортировки: Случайно
// Добавить вариант сортировки: Случайно
add_filter( 'woocommerce_get_catalog_ordering_args', 'custom_woocommerce_get_catalog_ordering_args' );
function custom_woocommerce_get_catalog_ordering_args( $args ) {
$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
if ( 'random_list' == $orderby_value ) {
$args['orderby'] = 'rand';
$args['order'] = '';
$args['meta_key'] = '';
}
return $args;
}
add_filter( 'woocommerce_default_catalog_orderby_options', 'custom_woocommerce_catalog_orderby' );
add_filter( 'woocommerce_catalog_orderby', 'custom_woocommerce_catalog_orderby', 100 );
function custom_woocommerce_catalog_orderby( $sortby ) {
$sortby['random_list'] = __('Случайно');
return $sortby;
}
Данный вариант сортировки может некорректно работать с пагинацией, т.к. при переходе по страницам будет генерировать новую случайную выборку. Но это не точно.
Вариант сортировки: По названию
// Добавить вариант сортировки: По названию
add_filter( 'woocommerce_get_catalog_ordering_args', 'custom_woocommerce_get_catalog_ordering_name_args' );
function custom_woocommerce_get_catalog_ordering_name_args( $args ) {
$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
if ( 'name_list' == $orderby_value ) {
$args['orderby'] = 'name';
$args['order'] = 'ASC';
$args['meta_key'] = '';
}
return $args;
}
add_filter( 'woocommerce_default_catalog_orderby_options', 'custom_woocommerce_catalog_name_orderby' );
add_filter( 'woocommerce_catalog_orderby', 'custom_woocommerce_catalog_name_orderby', 1 );
function custom_woocommerce_catalog_name_orderby( $sortby ) {
$sortby['name_list'] = 'По названию';
return $sortby;
}
Вариант сортировки: По меткам
// Добавить вариант сортировки: По меткам
add_filter( 'woocommerce_get_catalog_ordering_args', 'custom_woocommerce_get_catalog_ordering_tag_args' );
function custom_woocommerce_get_catalog_ordering_tag_args( $args ) {
$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
if ( 'tag_list' == $orderby_value ) {
$args['orderby'] = 'product_tag';//поле по которому сортируем
$args['order'] = 'ASC';//по возрастанию (ASC) или убыванию (DESC)
$args['meta_key'] = '';//по конкретному совпадению ключа
}
return $args;
}
add_filter( 'woocommerce_default_catalog_orderby_options', 'custom_woocommerce_catalog_tag_orderby' );
add_filter( 'woocommerce_catalog_orderby', 'custom_woocommerce_catalog_tag_orderby', 5 );
function custom_woocommerce_catalog_tag_orderby( $sortby ) {
$sortby['tag_list'] = 'По меткам';
return $sortby;
}
Сначала товары со скидкой
// Сортировка Сначала товары по акции
add_filter( 'woocommerce_get_catalog_ordering_args', 'wcs_get_catalog_ordering_args' );
function wcs_get_catalog_ordering_args( $args ) {
$orderby_value = isset( $_GET['orderby'] ) ? woocommerce_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
if ( 'on_sale' == $orderby_value ) {
$args['orderby'] = 'meta_value_num';
$args['order'] = 'DESC';
$args['meta_key'] = '_sale_price';
}
return $args;
}
add_filter( 'woocommerce_default_catalog_orderby_options', 'wcs_catalog_orderby' );
add_filter( 'woocommerce_catalog_orderby', 'wcs_catalog_orderby' );
function wcs_catalog_orderby( $sortby ) {
$sortby['on_sale'] = 'Сначала товары по акции';
return $sortby;
}
Работает странно: на одном сайте (с бОльшим количеством товаров) выводил акционные товары на первое место, а на другом сайте оставлял только акционные товары и другие не выводил.
Вариант сортировки: По наличию
// Сортировка по наличию
add_filter( 'woocommerce_get_catalog_ordering_args', 'custom_woocommerce_get_catalog_ordering_args' );
function custom_woocommerce_get_catalog_ordering_args( $args ) {
$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
if ( 'stock_list_asc' == $orderby_value ) {
$args['orderby'] = 'meta_value_num wp_posts.ID';
$args['order'] = 'ASC';
$args['meta_key'] = '_stock';
}
elseif ( 'stock_list_desc' == $orderby_value ) {
$args['orderby'] = 'meta_value_num wp_posts.ID';
$args['order'] = 'DESC';
$args['meta_key'] = '_stock';
}
return $args;
}
add_filter( 'woocommerce_default_catalog_orderby_options', 'custom_woocommerce_catalog_orderby' );
add_filter( 'woocommerce_catalog_orderby', 'custom_woocommerce_catalog_orderby' );
function custom_woocommerce_catalog_orderby( $sortby ) {
$sortby['stock_list_desc'] = 'Остаток: по убыванию';
$sortby['stock_list_asc'] = 'Остаток: по возрастанию';
return $sortby;
}
Товары не в наличии в конце
class iWC_Orderby_Stock_Status {
public function __construct() {
// Check if WooCommerce is active
if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
add_filter('posts_clauses', array($this, 'order_by_stock_status'), 2000);
}
}
public function order_by_stock_status($posts_clauses) {
global $wpdb;
// only change query on WooCommerce loops
if (is_woocommerce() && (is_shop() || is_product_category() || is_product_tag())) {
$posts_clauses['join'] .= " INNER JOIN $wpdb->postmeta istockstatus ON ($wpdb->posts.ID = istockstatus.post_id) ";
$posts_clauses['orderby'] = " istockstatus.meta_value ASC, " . $posts_clauses['orderby'];
$posts_clauses['where'] = " AND istockstatus.meta_key = '_stock_status' AND istockstatus.meta_value <> '' " . $posts_clauses['where'];
}
return $posts_clauses;
}
}
new iWC_Orderby_Stock_Status;
Удаляем варианты сортировки
Чтобы отключить стандартный вариант сортировки, нужно использовать следующую функцию:
function my_woocommerce_catalog_orderby( $orderby ) {
unset($orderby["price"]);
unset($orderby["price-desc"]);
return $orderby;
}
add_filter( "woocommerce_catalog_orderby", "my_woocommerce_catalog_orderby", 20 );
Варианты сортировки woocommerce:
- По-умолчанию (по сути по дате, либо если настроено по menu_order)
- По популярности (popularity, на основе количества продаж товаров)
- По рейтингу (rating)
- По дате (date, игнорирует menu_order)
- По возрастанию цены (price)
- По убыванию цены (price-desc)
Переименовываем варианты сортировки
Это можно сделать с помощью переводов либо функцией:
// Переименовать методы сортировки
add_filter( 'woocommerce_catalog_orderby', 'misha_rename_default_sorting_options' );
function misha_rename_default_sorting_options( $options ){
$options[ 'date' ] = 'Сначала новинки';
return $options;
}
Сортировка radio кнопками
Изменяем локальный файл шаблона woocommerce/orderby/orderby.php c
<select name="orderby" class="orderby" aria-label="<?php esc_attr_e( 'Shop order', 'woocommerce' ); ?>">
<?php foreach ( $catalog_orderby_options as $id => $name ) : ?>
<option value="<?php echo esc_attr( $id ); ?>" <?php selected( $orderby, $id ); ?>><?php echo esc_html( $name ); ?></option>
<?php endforeach; ?>
</select>
на
<div aria-label="<?php esc_attr_e( 'Shop order', 'woocommerce' ); ?>">
<?php foreach ( $catalog_orderby_options as $id => $name ) : ?>
<label><input type="radio" name="orderby" class="orderby" value="<?php echo esc_attr( $id ); ?>" <?php checked( $orderby, $id ); ?>><?php echo esc_html( $name ); ?></label>
<?php endforeach; ?>
</div>
И прописываем небольшой скрипт:
jQuery(function(i) {
i(".woocommerce-ordering").on("change", "input.orderby", function() {
i(this).closest("form").submit();
})
});
Сортировка по двум условиям
Данное решение сам еще не тестировал
add_action( 'pre_get_posts', 'mik_exclude_category' );
function mik_exclude_category( $query ) {
if ( $query->is_main_query() ) {
$query->set( 'meta_key', '_stock_status' );
$query->set( 'orderby', array('meta_value' => 'ASC', 'date' => 'DESC') );
}
}
или еще вариант
add_filter( 'woocommerce_shortcode_products_query', function( $args, $atts, $loop_name ){
if( $loop_name == 'product_category'){
$args['meta_key'] = '_stock_status';
$args['orderby'] = array('meta_value' => 'ASC', 'menu_order' => 'ASC');
}
return $args;
}, 10, 3);
[site-socialshare]
Случайная сортировка тоже работает некорректно. Если у вас одна страница с товарами, то проблем нет, но если страниц несколько, то на последующих страницах также происходит повторная сортировка, в результате чего товары могут повторяться
Спасибо! Учту этот момент.
Куда добавляем? Где добавляем??? Какой файл?
В functions.php
Как сделать чтобы от меньшего в большему шли по цене? Настройки вуки не работают
Таким вопросом не задавался. т.к. сортировка по цене есть в базовой комплектации. А если она не работает, то нужно устранить причины этого (возможно какой-то плагин или кастомная функция).
А как добавить сортировку по конкретному произвольному полю
Я и сам думал об этом, и пришел к выводу что сортировку можно сделать только по числовому полю и только при условии что данный параметр хотя бы со значением 0 будет у всех товаров. Но конкретной реализацией еще не занимался.
Подскажите пожалуйста! Как сделать чтоб была сортировка по «Распродажам»?
Принцип сортировки, как я понимаю, состоит в том чтобы сортировать по свойству которое есть у всех товаров. А «Распродажа» это специфическое состояние товара, т.е. наличие заполненного поля sale_price. Уверен что можно как-то придумать чтобы сначала выводились товары со скидками (я еще такого не делал), но не уверен что это удастся именно через сортировку.
Вопрос немного в сторону, но может поможете…
Можно сделать сортировку не выпадающим меню, а с помощью радио (input type=»radio»)?
Вообще тупик… не могу нигде найти такой инфы…
ну или может плагин какой так умеет?
Могу предположить, что Вам нужно в локальной папке шаблонов woocommerce изменить файл orderby/orderby.php, именно в нем создается данный фильтр. т.е. переделать тэг select и option на input type=»radio».
Дополнение: попытался это сделать, но нужно также переопределить функцию/скрипт изменения поля и функцию select, без этого не работает. Где это делается не знаю.
Дополнение 2: нашел нужный скрипт! Описал в статье как изменить select на radio кнопки. Способ 100% рабочий — проверил (по крайней мере на самой новой версии 4.0).
А как отсортировать цену по возрастанию, но что бы товары без цены или за ноль были в конце списка!
Пробовал вот этот код, он много где в интернете есть, но не работает, товары вообще пропадают.
// Товары без цены или с ценой равной нулю будут в конце списка
add_filter('posts_clauses', 'order_by_no_price', 50, 2);
function order_by_no_price($posts_clauses) {
global $wpdb;
if (!is_admin() && is_woocommerce() && (is_shop() || is_product_category() || is_product_tag() || is_product_taxonomy())) {
if($posts_clauses['join']!=' LEFT JOIN wp_wc_product_meta_lookup wc_product_meta_lookup ON wp_posts.ID = wc_product_meta_lookup.product_id '){
$posts_clauses['join'] = $posts_clauses['join'] . " LEFT JOIN wp_wc_product_meta_lookup wc_product_meta_lookup ON wp_posts.ID = wc_product_meta_lookup.product_id ";
}
$posts_clauses['orderby'] = "wc_product_meta_lookup.min_price > 0 DESC, " . $posts_clauses['orderby'];
}
return $posts_clauses;
}
Попробовал данный код. Но у меня он не также не работает — все товары исчезают. Я думаю, что нужно каким то образом переделывать сам фильтр сортировки price, но как это сделать сейчас не знаю. На будущее себе пометил.
А подскажите пожалуйста, как можно сделать сортировку в алфавитном порядке???А Б В Г Д Е Ё Ж З ….. не хочу я 69баксов отдавать за фигню
В этой статье описан такой вариант сортировки — По названию. Вставляйте в файл functions.php
Товары не в наличии в конце
увы но код не работает
Может быть. Не буду спорить.
Этот код лично не проверял. Иногда попадаются решения, я их сохраняю на будущее, чтобы вернуться если что.
Но данный код не пробовал. Если получится его доработать, обязательно выложу.