#wordpress #woocommerce
Вопрос:
Допустим, есть атрибут продукта «бренд» со следующими терминами:
- Марка А
- Марка B
- Марка C
Предположим также, что порядок меню этих терминов в разделе продукты > атрибуты >> размер был упорядочен как таковой:
- Марка C
- Марка А
- Марка B
Как я могу отсортировать товары на странице магазина по порядку меню атрибутов? Так, например:
- Продукт марки C
- Бренд продукта
- Продукт марки B
Предположим, что у каждого продукта есть только один термин атрибута бренда.
До сих пор я полагал, что код, скорее всего, будет включать изменение запроса с помощью pre_get_posts
крючка, но у меня возникли трудности с настройкой порядка таким образом.
Комментарии:
1. Вы можете показать, что вы придумали?
2. @HowardE Не так уж много… просто попробовал tax_query, но, конечно, все, что он делает, — это показывает продукты с определенными условиями. Что мне действительно нужно, так это своего рода значение порядка «menu_order», но вместо обычного заказа продукта он использует атрибут «порядок». Или какой-то способ определения порядка на основе порядка в пользовательском массиве также будет работать.
3. @HowardE Другим вариантом может быть сохранение атрибутов в качестве метаданных, что дает доступ к метазапросу. Однако это нежелательно, потому что таблица postmeta уже очень велика на сайте. Я все еще не думаю, что это сработает, потому что, хотя я получил бы доступ к значению meta_key orderby, для значений заказа по-прежнему существуют только ASC и DESC. Таким образом, он просто идет в алфавитном порядке, а не в каком-либо порядке меню или пользовательском порядке массивов.
Ответ №1:
Поскольку get_terms() возвращает порядок, который мы установили для наших атрибутов, мы можем получить эти идентификаторы и использовать их в качестве сортировки.
//Change taxonomy if you need.
$terms = get_terms( array('taxonomy' => 'pa_brand','fields' => 'ids'));
Оттуда мы можем использовать woocommerce_product_query
для изменения нашего запроса.
И, наконец, установите порядок нашего запроса по term_id
ASC или DESC.
Вот мое решение
function sort_products_by_brand( $q ) {
$terms = get_terms( array('taxonomy' => 'pa_brand','fields' => 'ids'));
$tax_query = $q->get('tax_query');
$tax_query[] = array(
'taxonomy' => 'pa_brand',
'field' => 'term_id',
'terms' => $terms,
);
$q->set( 'tax_query', $tax_query);
$q->set( 'orderby', 'term_id' );
// $q->set( 'order', 'DESC' ); // by default is ASC so uncomment if you want DESC.
}
add_action( 'woocommerce_product_query', 'sort_products_by_brand' );
Комментарии:
1. Это действительно изменило порядок, но он не соответствует порядку меню для условий. Я не верю, что для WP_Query существует значение порядка «term_id»: developer.wordpress.org/reference/classes/wp_query/. …
2. Да, вы правы. Idk почему работал на 1-м месте для меня, так что, наверное, у меня был какой-то кэш idk. Вычеркните этот ответ
Ответ №2:
Ответ Honk31 хорошо сработал для меня. Мне просто пришлось немного изменить его.
add_action( 'pre_get_posts', 'jwd_modify_product_query' );
function jwd_modify_product_query($query) {
if ( !is_admin() amp;amp; $query->is_main_query() amp;amp; is_post_type_archive( 'product' ) ) {
$query->set( 'orderby', 'pa_brand' );
}
}
// https://wordpress.stackexchange.com/a/363654/94213
// Answer by honk31
add_filter('posts_clauses', 'jwd_orderby_tax_clauses', 10, 2 );
function jwd_orderby_tax_clauses($clauses, $wp_query) {
global $wpdb;
$orderby = isset($wp_query->query_vars['orderby']) ? $wp_query->query_vars['orderby'] : false;
if ($orderby amp;amp; $orderby === 'pa_brand') {
$clauses['join'] .= <<<SQL
LEFT OUTER JOIN {$wpdb->term_relationships} ON {$wpdb->posts}.ID={$wpdb->term_relationships}.object_id
LEFT OUTER JOIN {$wpdb->term_taxonomy} USING (term_taxonomy_id)
LEFT OUTER JOIN {$wpdb->terms} USING (term_id)
SQL;
$clauses['where'] .= " AND (taxonomy = '{$orderby}' OR taxonomy IS NULL)";
$clauses['groupby'] = "object_id";
$clauses['orderby'] = "{$wpdb->terms}.term_order ASC";
$clauses['orderby'] .= ", {$wpdb->posts}.post_name ASC";
}
return $clauses;
}
Еще один шаг, который необходим, — это использование простого плагина для пользовательских заказов. Плагин добавляет term_order
столбец в таблицу терминов, по которому код использует сортировку. Перетащите, чтобы изменить порядок терминов в разделе продукты > атрибуты >> бренд. На самом деле мне пришлось переместить все термины, чтобы правильно отсортировать порядок.
Однако атрибуты WooCommerce уже имеют функцию перетаскивания и перетаскивания. Возможно, можно сделать что-то подобное и без этого плагина.