Сортировка товаров по атрибуту и мета полям Woocommerce

Изменить стандартную сортировку отображения товаров в каталоге довольно просто, если конечно использовать стандартные мета поля, а не атрибуты.
Для изменения сортировки есть специальный фильтр woocommerce_get_catalog_ordering_args, давай посмотрим как он работает.
Предположим мы хотим сделать сортировку по названию товара для этого создадим функцию, и пропишем необходимые переменные.
add_action( 'woocommerce_get_catalog_ordering_args', 'new_sort' ); function new_sort($args){ $args['order'] = 'ASC'; $args['orderby'] = 'title'; return $args; }
Вместо значения «title» можно подставить любое из существующих полей в бд например author или status. Если в переменную «orderby» прописать несуществующие поле, то каталог покажет уведомление об отсутствие товаров.
Так же можно сделать сортировку по метаполю, которых у товара ни так уж и мало:
- _price (цена)
- _sku (артикул)
- _stock_status (Наличие)
- _stock (Кол-во товаров в наличие)
- _weight (Вес товара)
- _length — Длина
- _width — Ширина
- _height — Высота
Пример сортировки по Артикулу
function new_sort($args){ $args['order'] = 'ASC'; $args['meta_key'] = '_sku'; $args['orderby'] = 'meta_value'; return $args; }
Предположим у нас есть атрибут размер или цвет, с альтернативным названием (Слаг) color и razmer.
Как сортировать по атрибутам, если значения не сохраняются отдельной ячейкой pa_color и pa_razmer, как это делается с Артикулом или Ценой товара.
Пример из PhpMyAdmin таблица wp_postmeta
Сохраняются атрибуты товара в поле meta_key со значением _product_attributes, и хранится в виде сериализованного массива. Естественно сортировать по таким данным будет не правильно, и результата не будет.
Чтобы убедиться в этом, сделайте обычный sql запрос в phpmyadmin, только не забываем подставить ID товара.
SELECT * FROM `wp_postmeta` WHERE post_id='id продукта'
Что делать?
Как вариант сохранять атрибуты товара в базе данных как отдельные записи, например вот так:
Для это задачи есть специальная функция update_post_meta, которая должна выполняться после нажатия кнопки обновить внутри карточки товара.
В файле function.php вашей темы пишем следующий код.
//Для обычного товара add_action( 'woocommerce_process_product_meta_simple', 'update_attr_to_meta' ); //Для вариативного товара add_action( 'woocommerce_process_product_meta_variable', 'update_attr_to_meta' ); function update_attr_to_meta($post_id){ //Проверяем наличие атрибутов if(isset($_POST['attribute_names']) and !empty($_POST['attribute_names'])){ //Перебираем массив с атрибутами foreach($_POST['attribute_names'] as $num=>$pa_name){ //Проверяем добавлено ли значение к атрибуту if(isset($_POST['attribute_values'][$num])){ //Если у атрибута несколько значений, берём самое первое if(is_array($_POST['attribute_values'][$num])){ $pa_value=$_POST['attribute_values'][$num][0]; }else{ //Если одно, обычно это Индивидуальный атрибут $pa_value=$_POST['attribute_values'][$num]; } //Обновляем мета данные всех добавленных атрибутов update_post_meta($post_id,'_'.$pa_name,$pa_value); } } } }
Обратите внимание, что добавление нижнего подчёркивания к _pa_name скрывает его отображение в Произвольных полях.
Если нужно добавить мета поля определённых атрибутов, строчку
update_post_meta($post_id,'_'.$pa_name,$pa_value);
Меняем на нижнюю строку, предварительно заменив строку pa_razmer на слаг вашего атрибута,например pa_color, pa_cvet,pa_shirina и т.д
if($pa_name=='pa_razmer')update_post_meta($post_id,'_'.$pa_name,$pa_value);
Что делает php скрипт?
При сохранение товара в админ.панели, проверяются добавленные атрибуты, и они сохраняются в БД.
Предупреждение! Для одного атрибута по которому предполагается сортировка, может быть добавлено лишь ОДНО значение, иначе будет взято самое первое из массива.
Когда у всех товаров будут добавлены мета поля , в нашем случае _pa_razmer и _pa_color мы можем выполнить сортировку
Сортировка по Размеру
add_action( 'woocommerce_get_catalog_ordering_args', 'new_sort'); function new_sort($args){ $args['order'] = 'ASC'; $args['meta_key'] = '_pa_razmer'; $args['orderby'] = 'meta_value_num'; return $args; }
Сортировка по цвету
add_action( 'woocommerce_get_catalog_ordering_args', 'new_sort'); function new_sort($args){ $args['order'] = 'ASC'; $args['meta_key'] = '_pa_color'; $args['orderby'] = 'meta_value'; return $args; }
В моём случае нужно было сделать сортировку уже заполненному каталогу, в котором более 5000 товаров, поэтому понадобилась ещё одна функция, которая заполнит мета поля Размер и Цвет каждому товару автоматически.
Данную функцию нужно выполнить всего один раз, а затем либо удалить её из файла function.php , либо закоментировать её, чтобы не создавать лишнюю нагрузку на базу данных.
add_action('woocommerce_loaded','new_attribute_to_meta'); function new_attribute_to_meta(){ global $wpdb; $num=3000; //Кол-во обрабатываемых записей foreach(wc_get_products(array('numberposts' => $num)) as $pr){ foreach($pr->get_attributes() as $key=>$attr){ $val=wc_get_product_terms( $pr->get_id(), $attr->get_name(), array( 'fields' => 'all' ) ); if($key=='pa_razmer' or $key=='pa_marka' or $key=='pa_size'){ update_post_meta($pr->get_id(),'_'.$key,$val[0]->name); } } } }
Обратите внимание на условие, я использую СЛАГ существующего атрибута, в вашем случае слаг атрибута может иметь другое название. Данную функцию так же нужно подключить в файл function.php, при условие если необходимо создать мета поля уже существующим товарам.
Анатолий
Делаю по этой инструкции, на первый взгляд всё работает, но на самом деле у меня сортировка происходит не по атрибутам, а по их ID. Т.е. в ‘meta_value’ хранится не значение атрибута, а его ID. Подскажите, пожалуйста, какой ещё момент я упускаю из виду?