Search code examples
wordpresswoocommerceadvanced-custom-fieldscustom-post-typeelementor

Custom Query Filter for Elementor Posts by relationship field (ACF)


I have a custom post type setup called 'Artists'. Each Single Artist is a page (artist profile if you wish), has a list of products that are associated with that artist via the relationship field type through Advanced Custom Fields (ACF). I need the products to be displayed within their categories on the artist page. So within Elementor I need to specify a 'Query Filter ID' to simply split the products into categories.

What I have tried so far

I am trying to display only products from a certain category in a list via a custom query as I need to generate a Query ID.

I've been trying a bunch of different ways to do this but now I'm at a loss. The latest code I have is here... what am I missing?

/** Product category 'SOFTWARE' **/
add_filter( 'software_product', 'product_category_software' );

function product_category_software( $variable ) {

    $query_args = array(
       'post_type' => 'product',
       'tax_query' => array(
            array(
                'taxonomy' => 'category',
                'field'    => 'slug',
                'terms'    => 'software', 
            ),
        ),
     );
return $variable;
}

Solution

  • Answer

    You need to use this

    https://developers.elementor.com/custom-query-filter/#Using_the_Custom_Filter

    arbitrary_name_query_id - the QUERY ID that you fill in the Elementor field,

    the code to be placed within functions.php:

    add_action( 'elementor/query/arbitrary_name_query_id', function( $query ) {
        $meta_query = $query->get( 'meta_query' ); 
        $meta_query[] = [ 
            'key'     => 'acf_key', // put ACF relationship field name 
            'value'   => get_the_ID(), 
            'compare' => '=', 
        ]; 
        $query->set( 'meta_query', $meta_query ); 
    } ); 
    

    Regarding to the given code

    First of all, as Wordpress Documentation on filters says:

    They (i.e. filters) provide a way for functions to modify data of other functions.

    Which means that the filter function, in this case it's product_category_software, receives data that subsequntly modifies and returns it back:

    add_filter( 'software_product', 'product_category_software' );
    function product_category_software( $variable ) { // receive $variable
    
        /**
         * Modify $variable here
         */
    
        return $variable; // return modified $variable
    }
    

    In your case product_category_software doesn't modify what receives, but introduces new peace of data $query_args which makes no sence, since it is not going to be returned.

    Secondly, the first argument of the add_filter function should be an existent filter name, the software_product is not.

    Thirdly, the correct name of the taxonomy of product categories is product_cat.

    Getting products from a certain category

    Aproach #1 Modfying main query with pre_get_posts

    function your_arbitrary_name( $query ) { // receive
        if ( ! is_admin() && is_post_type_archive( 'product' ) && $query->is_main_query() ) {
            $tax_query = array(
                array(
                    'taxonomy' => 'product_cat',
                    'field'    => 'slug',
                    'terms'    => array( 'software' ),
                )
            );
    
            $query->set( 'meta_query', $tax_query ); // modify
        }
        return $query; // and return
    }
    add_action( 'pre_get_posts', 'your_arbitrary_name', 20 );
    

    Aproach #2 Use wc_get_products or WC_Product_Query

    Example, use in your Controller or even in the template:

    $args = array(
        'category' => array( 'software' ),
    );
    $products = wc_get_products( $args );
    

    Read the Docs about wc_get_products and WC_Product_Query