WooCommerce catalog order by a custom range based on metadata

71 views Asked by At

Using custom field ID: _diameter

woocommerce_wp_text_input(
    array(
        'id' => '_diameter',
        'label' => __('Diameter', 'woocommerce'),
        'placeholder' => __('Enter diameter...', 'woocommerce'),
        'desc_tip' => 'true',
        'description' => __('Enter the diameter for this product.', 'woocommerce'),
        'type' => 'number',
        'custom_attributes' => array(
            'step' => 'any',
            'min' => '0'
        )
    )
);

It has stored values for Wheels from. 15-28

After user pick YearMakeModel of his car plugin writes two values : Min_Diameter, Max_Diameter to Cookie...

Now I need to sort my wheels based on those two values. Lets say user picks car and values are Min: 19, Max: 21 then it should sort wheels ( Not filter ) by those values from 19-21 and then others .

According to documentation : WP_Query this should do the trick. But for some reason not working. Tried with Between and IN

function custom_sort_by_recommended( $sort_args ) {
    if ( isset( $_GET['orderby'] ) && $_GET['orderby'] == 'recommended' ) {
        // Read cookie values
        $min_diameter = isset( $_COOKIE['Min_Diameter'] ) ? intval( $_COOKIE['Min_Diameter'] ) : 0;
        $max_diameter = isset( $_COOKIE['Max_Diameter'] ) ? intval( $_COOKIE['Max_Diameter'] ) : PHP_FLOAT_MAX;

        // Modify the query args
        $sort_args['meta_query'] = array(
            'relation' => 'AND',
            array(
                'key'     => '_diameter',
                'value'   => array( $min_diameter, $max_diameter ),
                'compare' => 'BETWEEN',
            )
            
        ); 
                // Custom sorting order
        $sort_args['orderby'] = array(
            'meta_value_num' => 'ASC', // Sort by diameter ascending
        );
      
    }
    return $sort_args;
}
1

There are 1 answers

0
LoicTheAztec On BEST ANSWER

I suppose that you have hooked your function in woocommerce_get_catalog_ordering_args hook.

I also suppose that you added a custom "recommended" sorting option, something like:

add_filter( 'woocommerce_catalog_orderby', 'add_catalog_orderby_recommended' );
function add_catalog_orderby_recommended( $orderby ) {
    $orderby['recommended'] = __('Sort by recommended', 'woocommerce');
    return $orderby;
}

Now, note that $sort_args only handles 'orderby' and 'order', but not 'meta_query'.

Then you will replace your existing hooked function with the following:

add_filter( 'woocommerce_get_catalog_ordering_args', 'catalog_ordering_by_recommended', 10, 3 );
function catalog_ordering_by_recommended( $args, $orderby, $order ) {
    if ( isset( $_GET['orderby'] ) && $_GET['orderby'] === 'recommended' ) {
        // Custom sorting order
        $args['orderby'] = array(
            'meta_value_num' => 'ASC', // Sort by diameter ascending
        );
    }
    return $args;
}

add_filter( 'woocommerce_product_query', 'product_query_by_recommended', 10, 1 );
function product_query_by_recommended( $q ) {
    if ( isset($_GET['orderby']) && $_GET['orderby'] === 'recommended' ) {
        // Read cookie values
        $min_diameter = isset( $_COOKIE['Min_Diameter'] ) ? intval( $_COOKIE['Min_Diameter'] ) : 0;
        $max_diameter = isset( $_COOKIE['Max_Diameter'] ) ? intval( $_COOKIE['Max_Diameter'] ) : PHP_FLOAT_MAX;

        $meta_query = $q->get('meta_query');

        $meta_query['relation'] = 'AND';

        $meta_query[] = array(
            'key'     => '_diameter',
            'value'   => array( $min_diameter, $max_diameter ),
            'compare' => 'BETWEEN',
            'type'    => 'NUMERIC',
        );

        $q->set('meta_query', $meta_query);
        $q->set('orderby', array(
            'meta_value_num' => 'ASC', // Sort by diameter ascending
        ) );
    }
}

It should work.