Как заказать товары WooCommerce по запросу в меню

#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 уже имеют функцию перетаскивания и перетаскивания. Возможно, можно сделать что-то подобное и без этого плагина.