1

Looking to return each occurrence (product) found in name where name is comma separated, e.g. [woo_products_by_name name="shoe,shirt"] If I do not explode name then nothing is returned as only shoe,shirt is seen. If explode is used then the query is not selective and it appears that all products are returned. If only 'name' => $name is used and one verse two products as described above are specified, then the query works as expected. Would like to return a match for each item so in this example, to products would be returned.

function woo_products_by_name_shortcode( $atts, $content = null ) {

        // Get attribuets
        extract(shortcode_atts(array(
        'name' => ''
        ), $atts));
        //$name = explode(",", $atts['name']);

        ob_start();
        // Define Query Arguments
        $loop = new  WP_Query( array(
                'post_type'      => 'product',
                'posts_per_page' => 10,
                'name'           => explode(",",$name)
        ));

        // Get products number
        $product_count = $loop->post_count;

        echo '<pre>'; print_r($loop->posts); echo '</pre>';
        return ob_get_clean();
}
add_shortcode("woo_products_by_name", "woo_products_by_name_shortcode");

2 Answers 2

1

This can be done using a very light SQL request that will gives product IDs for your product slugs. Then using WP_Query post__in argument, you will get what you expect:

function woo_products_by_name_shortcode( $atts, $content = null ) {

    // Get attribuets
    extract(shortcode_atts(array(
        'name' => ''
    ), $atts));

    if( empty($name) ) return;

    // Format product slugs string
    $name = str_replace(",", "','", $name);

    global $wpdb;
    // Get the corresponding products ids
    $ids = $wpdb->get_col( "SELECT ID FROM {$wpdb->prefix}posts
        WHERE post_type = 'product' AND post_name IN('$name')" );

    ob_start();

    // Define Query Arguments
    $loop = new  WP_Query( array(
        'post_type'      => 'product',
        'posts_per_page' => -1,
        'post__in'       => $ids
    ));

    // Get products number
    $product_count = $loop->post_count;

    echo '<pre>'; print_r($loop->posts); echo '</pre>';

    return ob_get_clean();
}
add_shortcode("woo_products_by_name", "woo_products_by_name_shortcode");

Code goes in function.php file of your active child theme (or active theme). Tested and works.


Testing output in html/php:

<?php echo do_shortcode( "[woo_products_by_name name='shoe,shirt']" ); ?>

Testing output in Wordpress text editor:

[woo_products_by_name name='shoe,shirt']
Sign up to request clarification or add additional context in comments.

Comments

1

Ideally you would use the id or other queryable attribute in your shortcode instead, the query would be much easier if you did - but defeats the get_by_name methodology.

You're probably looking at running two separate queries within a foreach loop, or better yet drop the WP_Query and instead use get_page_by_path()

function woo_products_by_name_shortcode( $atts, $content = null ) {

    // Get attribuets
    extract(shortcode_atts(array(
    'name' => ''
    ), $atts));

    $name_array = explode(",", $atts['name']);

    ob_start();

    $products = array();
    foreach( $name_array as $product ){
        $products[$product] = get_page_by_path( $product, OBJECT, 'product' );
    }

    // Get products number
    $product_count = count( $name_array );

    echo '<pre>'; print_r($products); echo '</pre>';
    return ob_get_clean();
}
add_shortcode("woo_products_by_name", "woo_products_by_name_shortcode");

Since you mentioned the need for using WP_Query, you'll be resorting to getting the id's either by using the $wpdb class with an sql query, and then running WP_Query with those IDs - or you can get the ID's from get_page_by_path and query those using the post__in argument (note the double underscore)

function woo_products_by_name_shortcode( $atts, $content = null ) {

    // Get attribuets
    extract(shortcode_atts(array(
        'name' => ''
    ), $atts));

    $name_array  = explode(",", $atts['name']);
    $product_ids = array();

    foreach( $name_array as $product ){
        $product = get_page_by_path( $product, OBJECT, 'product' );
        $product_ids[] = $product->ID;
    }

    ob_start();
    // Define Query Arguments
    $loop = new WP_Query( array(
        'post_type'      => 'product',
        'posts_per_page' => 10,
        'post__in'       => $product_ids
    ));

    // Get products number
    $product_count = $loop->post_count;

    echo '<pre>'; print_r($loop->posts); echo '</pre>';
    return ob_get_clean();
}
add_shortcode("woo_products_by_name", "woo_products_by_name_shortcode");

3 Comments

While this works, was looking to use WP_Query so that we might be able to query other fields using s to search for a word in the title or content. If best that I create a new question due to lack of clarity, happy to do so as this is technically a correct answer.
I've updated the answer to include a method of getting the id by sticking with get_page_by_path, and then looping through posts with those id's using the post__in argument for WP_Query. It's not exactly pretty but it should work. The gist being you need to get a queryable parameter from the name whether it's via $wpdb or a built in function like get_page_by_path
This worked and thank you for the answer but I was looking for what you suggested where you leverage a $wpdb query in order to get the ID and then run the respective WP_Query

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.