skip to Main Content

I have the below foreach loop running over an array of WooCommerce products, which are queried by the below query. This outputs the products in the menu_order, which is as expected, however what I need to do is to keep them in this order, EXCEPT products which as ‘featured products’. These should almost be ignored by the order parameter and always appear first in the foreach loop.

Is this possible?

// Get Products
$args = array(
  'status' => 'publish',
  'category' => $currentCat->slug,
  'orderby' => 'menu_order',
  'order' => 'ASC',
  'limit' => -1,
);
$productsData = wc_get_products( $args );

<? // For each product
foreach($productsData as $product): ?>
        
  <? if( $product['isFeatured'] ): ?>
    // Output featured product html here...
  <? else: ?>
    // Output other products HTML here...
  <? endif ?>
<? endforeach ?>

2

Answers


  1. Chosen as BEST ANSWER

    Managed to resolve this for my needs by performing 2 separate queries, and then merging them into an array (in the desired order). This ensures one query always appears before the other, whilst each query can still respect ordering parameters such as menu_order.

    // Featured products query
    $featuredArgs = array(
      'status' => 'publish',
      'category' => $currentCat->slug,
      'orderby' => 'menu_order',
      'order' => 'ASC',
      'limit' => 1,
      'tax_query' => array(
        array(
          'taxonomy' => 'product_visibility',
          'field'    => 'name',
          'terms'    => 'featured',
          'operator' => 'IN',
        ),
      ),
    );
    
    // Non-featured products query
    $nonFeaturedArgs = array(
      'status' => 'publish',
      'category' => $currentCat->slug,
      'orderby' => 'menu_order',
      'order' => 'ASC',
      'limit' => -1,
      'tax_query' => array(
        array(
          'taxonomy' => 'product_visibility',
          'field'    => 'name',
          'terms'    => 'featured',
          'operator' => 'NOT IN',
        ),
      ),
    );
    
    // Get products from each query (performed seperately so that we can control the order of products)
    $featuredProductsData = wc_get_products( $featuredArgs );
    $nonFeaturedProductsData = wc_get_products( $nonFeaturedArgs );
    
    // Merge both queries in the desired order
    $productsData = array_merge($featuredProductsData, $nonFeaturedProductsData);
    

  2. I haven’t tried this, but you could see if this works. I know this trick works with meta queries, so It might work with taxonomy queries too: the trick being to reference the tax queries by name in the orderby.

    $featured_tax_query[] = array(
        'taxonomy' => 'product_visibility',
        'field'    => 'name',
        'terms'    => 'featured',
        'operator' => 'IN',
    );
    $non_featured_tax_query = $featured_tax_query;
    $non_featured_tax_query['operator'] => 'NOT IN';
    
    $args = array(
      'status' => 'publish',
      'category' => $currentCat->slug,
      'orderby' => 'menu_order',
      'order' => 'ASC',
      'limit' => -1,
      'tax_query' => array('featured' => $featured_tax_query,
                           'non_featured' => $non_featured_tax_query),
      'orderby' => array(
        'featured' => 'ASC',
        'non_featured' => 'ASC',
      )
    );
    $featuredProductsData = wc_get_products( $args );
    

    If the above doesn’t work, you can break it out into 2 different queries like so:

    $tax_query[] = array(
        'taxonomy' => 'product_visibility',
        'field'    => 'name',
        'terms'    => 'featured',
        'operator' => 'IN',
    );
    
    // Get featured products
    $args = array(
      'status' => 'publish',
      'category' => $currentCat->slug,
      'orderby' => 'menu_order',
      'order' => 'ASC',
      'limit' => -1,
      'tax_query' => $tax_query,
    );
    $featuredProductsData = wc_get_products( $args );
    
    foreach($featuredProductsData as $product): ?>
        // Output featured product html here...
    <?php endforeach; ?>
    
    // Get non-featured products
    $tax_query['operator'] => 'NOT IN';
    $args['tax_query'] => $tax_query;
    $productsData = wc_get_products( $args );
    
    foreach($productsData as $product): ?>
        // Output other products HTML here...
    <?php endforeach; ?>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search