skip to Main Content

I have clothes products. One product is in multiples categories, like "gender" ("men" or "women") and "type" (such as "pants", "shirts", etc.).

I want to list all categories and subcategories of "type" from products that exist in "men" category.

ID of "type" category: 1696

$args = array(
  'taxonomy' => 'product_cat',
  'orderby'  => 'title',
  'order'    => 'ASC',
  'child_of'   => 1696,
);
$categories = get_terms( $args );
print_r($categories);

That code gives me all the categories under 1696, but I would like to get only the "type" categories from products that also are in "men" category.

Am I clear?

Thanks a lot for your help.

2

Answers


  1. Chosen as BEST ANSWER

    Thanks for your help, but it's not what I need.

    I found a way to achieve what I want. There must be a better way but here's how I did:

    I'm looping every products and put them in arrays if they are in the gender category ("femme" and "homme").

        $categories_femme = array(); // 1718
        $categories_homme = array(); // 1700
        
        $args = array(
            'post_type' => 'product',
            'posts_per_page' => -1
        );
        $loop = new WP_Query( $args );
        if ( $loop->have_posts() ): while ( $loop->have_posts() ): $loop->the_post();
    
          global $product;
    
          $p_id = $product->get_id();
          
          // FEMME
          if( has_term( 1718, 'product_cat' ) ) {
            $categories_femme[] = wp_get_post_terms($p_id, 'product_cat');
          }
          // HOMME
          if( has_term( 1700, 'product_cat' ) ) {
            $categories_homme[] = wp_get_post_terms($p_id, 'product_cat');
          }
    
        endwhile; endif; wp_reset_postdata();
    

    After that, I'm formating the array to get this structure of categories (one array per gender): array('term_id' => 'name_id', 'term_id' => 'name_id', 'term_id' => 'name_id');

        $categories_femme_formated = array();
        foreach ($categories_femme as $categorie_femme) {
          foreach ($categorie_femme as $categoriefemme) {
            $categories_femme_formated[$categoriefemme->term_id] = $categoriefemme->name;
          }
        }
        
        $categories_homme_formated = array();
        foreach ($categories_homme as $categorie_homme) {
          foreach ($categorie_homme as $categoriehomme) {
            $categories_homme_formated[$categoriehomme->term_id] = $categoriehomme->name;
          }
        }
    

    After that, I'm looping through all clothes categories and looking if this category ID exist in the array created just before. If yes, I'm adding this category to the menu.

        $args = array(
          'taxonomy' => 'product_cat',
          'hide_empty' => false,
          'parent'   => 1696
        );
        $product_cat = get_terms( $args );
    
        // FEMME
        $count_order = 100;
        foreach ($product_cat as $parent_product_cat)
        {
          $p_id = $parent_product_cat->term_id;
          if (array_key_exists($p_id, $categories_femme_formated)) {
            $count_order++;
            $menu_items[] = _custom_nav_menu_item( $categories_femme_formated[$p_id], get_term_link($p_id), $count_order, 11407 );
            
            $child_args = array(
                    'taxonomy' => 'product_cat',
                    'hide_empty' => false,
                    'parent'   => $parent_product_cat->term_id
                );
            $child_product_cats = get_terms( $child_args );
            $parent_order = $count_order;
            foreach ($child_product_cats as $child_product_cat)
            {
              $c_id = $child_product_cat->term_id;
              if (array_key_exists($c_id, $categories_femme_formated)) {
                $count_order++;
                $child_menu_id = 1000000 + $parent_order + 11407;
                $menu_items[] = _custom_nav_menu_item( $categories_femme_formated[$c_id], get_term_link($c_id), $count_order, $child_menu_id );
                
              }
            }
          }
        }
        
        // HOMME
        $count_order = 100;
        foreach ($product_cat as $parent_product_cat)
        {
          $p_id = $parent_product_cat->term_id;
          if (array_key_exists($p_id, $categories_homme_formated)) {
            $count_order++;
            $menu_items[] = _custom_nav_menu_item( $categories_homme_formated[$p_id], get_term_link($p_id), $count_order, 11408 );
            
            $child_args = array(
                    'taxonomy' => 'product_cat',
                    'hide_empty' => false,
                    'parent'   => $parent_product_cat->term_id
                );
            $child_product_cats = get_terms( $child_args );
            $parent_order = $count_order;
            foreach ($child_product_cats as $child_product_cat)
            {
              $c_id = $child_product_cat->term_id;
              if (array_key_exists($c_id, $categories_homme_formated)) {
                $count_order++;
                $child_menu_id = 1000000 + $parent_order + 11408;
                $menu_items[] = _custom_nav_menu_item( $categories_homme_formated[$c_id], get_term_link($c_id), $count_order, $child_menu_id );
                
              }
            }
          }
        }
    

    Just for everyone to understand, I'm calling this code inside a function called by:

    add_filter( 'wp_nav_menu_objects', 'my_dynamic_menu_items' );
    

    And here is the _custom_nav_menu_item function:

    function _custom_nav_menu_item( $title, $url, $order, $parent = 0 ){
      $item = new stdClass();
      $item->ID = 1000000 + $order + $parent;
      $item->db_id = $item->ID;
      $item->title = $title;
      $item->url = $url;
      $item->menu_order = $order;
      $item->menu_item_parent = $parent;
      $item->type = '';
      $item->object = '';
      $item->object_id = '';
      $item->classes = array();
      $item->target = '';
      $item->attr_title = '';
      $item->description = '';
      $item->xfn = '';
      $item->status = '';
      $item->icon = '';
      $item->nolink = '';
      $item->hide = '';
      $item->mobile_hide = ''; 
      $item->cols = ''; 
      $item->tip_label = '';
      $item->popup_type = 'wide';
      $item->popup_pos = '';
      $item->popup_cols = 'col-4';
      $item->popup_max_width = '';
      $item->popup_bg_image = '';
      $item->popup_bg_pos = ''; 
      $item->popup_bg_repeat = ''; 
      $item->popup_bg_size = ''; 
      $item->popup_style = '';
      $item->block = '';
      $item->preview = '';
      $item->preview_fixed = ''; 
      $item->current = '';
      $item->current_item_ancestor = '';
      $item->current_item_parent = '';
      return $item;
    }
    

    Thanks again for your help. :)


  2. Since wordpress only allows one id at a time for child_of argument, you could create a custom array and run get_terms for every parent category that you want.

    From the documentation:

    • child_of – (int) Term ID to retrieve child terms of. If multiple taxonomies are passed, $child_of is ignored. Default 0.
      wp_term_query
    
    $child_cats = array();
    
    $parent_cats = array(1696, {the other category id});
    
    $args = array(
      'taxonomy' => 'product_cat',
      'orderby'  => 'title',
      'order'    => 'ASC',
      'child_of'=> $parent_cat
    );
    
    foreach ($parent_cats as $parent_cat) 
    {
        $child_cats = array_merge($child_cats, get_terms($args));
    };
    
    print_r($child_cats);
    

    Let me know if that’s what you were looking for!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search