How to echo an array returned by a function

You cannot return an array from inside a shortcode, this will lead to the following error

Array to string convertion …..

The output from a shortcode needs to be a string, so you need to convert your array to a string. You also cannot echo anything inside a shortcode, neither can you use functions or template tags inside a shortcode which echos its output. In rare cases where you don’t have a choice, you can make use of output buffering, but this should be your last resort

To correctly create a shortcode from your function, you have to do something like this: (CAVEAT: Utested and only a demo to work from)

add_shortcode( 'my_shortcode', 'hsj_product_list' );

function hsj_product_list( $atts )
{

$attributes = shortcode_atts(
    array(
        'slug' => '',
    ),
    $atts,
    'my_shortcode'
);

$args = array(
    'post_type' => 'product',
    'tax_query' => array(
        'relation' => 'AND',
        array(
            'taxonomy' => 'product_cat',
            'field' => 'slug',
            'terms' => $attributes['slug']
        ) 
    )
);

$products = get_posts( $args );

$output="";

if ( $products ) {

    foreach( $products as $post ) {
        $product = wc_get_product( $post );
        $output .= $product->get_title();
    }

}
return $output;
}

As you can see, I have concatenated all the values I need into one string which is set to the variable $output. I have also made sure if there are no post that we output an empty string by defining $output="" before we start the foreach loop

You can use it as follow

[my_shortcode slug='my-slug']

A FEW NOTES

  • You would want to sanitize and validate the user inputs, in this case, the value passed to slug

  • IMO, if you are going to use do_shortcode, then you don’t need a shortcode. Simply use the function then and make the necessary changes to the function. This will be faster as shortcodes need to be parsed and prossed first making them slower than just the selfstanding function

  • Always check that you have an array value before passing it to a foreach loop. If an empty value is passed, this will lead to a PHP warning (a bug). I have already done that in my code above, so be sure to check it out

  • The above is just the basics of a shortcode, you should extend and modify and abuse it as you see fit in order to suite your needs