Viewed   109 times

I am trying to get the product categories from WooCommerce through a function in my WordPress theme

    function get_me_list_of($atts, $content = null)
        $args = array( 'post_type' => 'product', 'posts_per_page' => 10, 'product_cat' => $atts[0]);

        $loop = new WP_Query( $args );

        echo '<h1 class="upp">Style '.$atts[0].'</h1>';
        echo "<ul class='mylisting'>";
        while ( $loop->have_posts() ) : $loop->the_post(); 
        global $product; 

        echo '<li><a href="'.get_permalink().'">'.get_the_post_thumbnail($loop->post->ID, 'thumbnail').'</a></li>';
     echo '<li><a href="'.get_permalink().'">'.$loop->post->post_title.'</a></li>';

echo '<li><a href="">'.get_categories().'</a></li>';

        echo "</ul>";




The above code returns some products, but the product categories.

When I included echo '<li><a href="">'.get_categories().'</a></li>'; in the code above it returns as an array. How do I fix this?

How do i change this to get the product categories from WooCommerce?



  $taxonomy     = 'product_cat';
  $orderby      = 'name';  
  $show_count   = 0;      // 1 for yes, 0 for no
  $pad_counts   = 0;      // 1 for yes, 0 for no
  $hierarchical = 1;      // 1 for yes, 0 for no  
  $title        = '';  
  $empty        = 0;

  $args = array(
         'taxonomy'     => $taxonomy,
         'orderby'      => $orderby,
         'show_count'   => $show_count,
         'pad_counts'   => $pad_counts,
         'hierarchical' => $hierarchical,
         'title_li'     => $title,
         'hide_empty'   => $empty
 $all_categories = get_categories( $args );
 foreach ($all_categories as $cat) {
    if($cat->category_parent == 0) {
        $category_id = $cat->term_id;       
        echo '<br /><a href="'. get_term_link($cat->slug, 'product_cat') .'">'. $cat->name .'</a>';

        $args2 = array(
                'taxonomy'     => $taxonomy,
                'child_of'     => 0,
                'parent'       => $category_id,
                'orderby'      => $orderby,
                'show_count'   => $show_count,
                'pad_counts'   => $pad_counts,
                'hierarchical' => $hierarchical,
                'title_li'     => $title,
                'hide_empty'   => $empty
        $sub_cats = get_categories( $args2 );
        if($sub_cats) {
            foreach($sub_cats as $sub_category) {
                echo  $sub_category->name ;

This will list all the top level categories and subcategories under them hierarchically. do not use the inner query if you just want to display the top level categories. Style it as you like.

Tuesday, October 11, 2022

use the existing function get_page_by_path();

$product_obj = get_page_by_path( $slug, OBJECT, 'product' );

better explanation :

Thursday, December 8, 2022

Well I found the solve here

and here's the code :

$test = $_product->get_attributes();
if(!empty($test)) {
    $terms = get_the_terms($product_id, "pa_size");
    foreach ( $terms as $term ) {
    echo "<option>" . $term->name . "</option>";
} else {
    echo "Not Specified";
Wednesday, August 31, 2022

The action(s) you want are these:

add_action('woocommerce_update_product', 'productPublished');

add_action('woocommerce_new_product', 'productPublished');

function productPublished($product_id){

You can find them both (where they are triggered from) in the Woo source code here:

I actually looked them up backwards by first finding where the source code for saving products was, and then looked for hooks in those methods (create/update).

 //found on Line 134 method create
 do_action( 'woocommerce_new_product', $id );

 //found on Line 237 method update
 do_action( 'woocommerce_update_product', $product->get_id() );

You'll also have to change this line:

function productPublished ($ID , $post , $update){
    $product = wc_get_product( $post->ID);


function productPublished($product_id){
    $product = wc_get_product( $product_id);

I don't think the other arguments (that are missing) matter to your code. Such as if it's an update or a new product, I also don't see $post used except to get the product ID, which we already have.

UPDATE (determine args for callback)

If you are not sure about the callback's arguments, you can look in the source code (as I did above) Or if you can find it in documentation Or as a last resort you can simply output them. The best way to output them is one of these 3

  • func_get_args() - "Returns an array comprising a function's argument list"
  • debug_print_backtrace() - "Prints a backtrace (similar to stacktrace)"
  • Exception::getTraceAsString() try/catch and throw an exception to output the stacktrace

Here is an example I built with a minimally/simplified working hook system modeled after WordPress's. For testing reasons and because it's really not that hard to build when you know how it works:

//global storage (functions, not classes)
global $actions;
$actions = [];

//substitute wordpress add_action function (for testing only) 
function add_action($action, $callback, $priorty=10, $num_args=1){
    global $actions;
    $actions[$action][] = [
         'exec' => $callback,
         'num_args' => $num_args

//substitute wordpress do_action function (for testing only) 
function do_action($action, ...$args){
    // PHP5.6+ variadic (...$args) wraps all following arguments in an array inside $args (sort of the opposite of func_get_args)
    global $actions;

    if(empty($actions[$action])) return;
    //sort by priory
    usort($actions[$action], function($a,$b){
       //PHP7+ "spaceship" comparison operator (<=>)
       return $b['priorty']<=>$a['priorty'];

    foreach($actions[$action] as $settings){
        //reduce the argument list
        call_user_func_array($settings['exec'], array_slice($args, 0, $settings['num_args']));

//test callback
function callback1(){
     echo "nn".__FUNCTION__."n";

//test callback
function callback2(){
    echo "nn".__FUNCTION__."n";
        //throw an empty exception
        throw new Exception;
    }catch(Exception $e){
         //pre tags preserve whitespace (white-space : pre)
        echo "<pre>";
        //output the stacktrace of the callback
        echo $e->getTraceAsString();
        echo "nn</pre>";

//Register Hook callbacks, added in opposite order, sorted by priority
add_action('someaction', 'callback2', 5, 4);
add_action('someaction', 'callback1', 1, 5);

//execute hook
do_action('someaction', 1234, 'foo', ['one'=>1], new stdClass, false);


<pre>#0 [...][...](25): callback2(1234, 'foo', Array, Object(stdClass))
#1 [...][...](52): do_action('someaction', 1234, 'foo', Array, Object(stdClass), false)
#2 {main}


    [0] => 1234
    [1] => foo
    [2] => Array
            [one] => 1

    [3] => stdClass Object
    [4] =>


Stacktrace As you can see in the first output, we have a complete stacktrace of the application (minus the redacted info), including the function calls and the arguments used for those calls. Also note in this example, I registered it 2nd but the priority (set in add_action) made it execute first. Lastly, only 4 of the 5 arguments were used (also do to how add_action was called).

So do_action was called like this (with 'action' and 5 other args):

 do_action('someaction', 1234, 'foo', Array, Object(stdClass), false)

And the actual callback was called like this (without 'action' and only 4 other args):

 callback2(1234, 'foo', Array, Object(stdClass))

Function Arguments This is a bit more strait forward, but it doesn't give you the original call so you won't know the maximum number of args (which you can get from the call to do_action in the stacktrace). But if you just want a quick peek at the incoming data, it's perfect. Also I should mention this one uses all 5 args, which you can clearly see in the array for the second output. The [4] => is false, this is typically how print_r displays false (as just empty).

Debug Backtrace Unfortunately, debug_print_backtrace is disabled (for security reasons) in the sandbox, and Exception stacktrace is heavily redacted (typically it has file names and lines where functions are called from and located at) also for security reasons. Both of these can return arguments from things like connecting to the Database, which would contain the DB password in plain text, just for example. Anyway, debug_print_backtrace is pretty close to what an exception stack trace looks like anyway.


But in any case, this should give you an idea of what the data looks like. We can use functions like this (and Reflection) to interrogate the application at run time. I am sure there are other/more ways to do similar things too.

PS. It should go without saying, but I will say it anyway, these methods above work with any PHP function, and can be quite useful. Also as noted above, you should never show stacktraces on a live production machine.

Anyway, good luck.

Tuesday, August 30, 2022

To get the product id from the WC_Subscription Object, you will need to loop through order items (as you can have many) using the method get_items() like:

$order_items = $subscription->get_items();

// Loop through order items
foreach ( $order_items as $item_id => $item ) {
    // Get the WC_Product_Subscription Object
    $product = $item->get_product();

    // To get the subscription variable product ID and simple subscription  product ID
    $product_id = $item->get_product_id();

    // To get the variation subscription product ID
    $variation_id = $item->get_variation_id();

    // Or to get the simple subscription or the variation subscription product ID
    $_product_id = $product->get_id();

Tested and works.


  • How to get the user ID from a WC_Subscription instance Object
  • How to get Order Details from a WC_Subscription instance Object
Friday, October 14, 2022
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :