1
votes

I'm trying to add custom content before shop content but only when viewing products in specific category with this category childs.

Thoes categories are: main category - 'events', child categories - 'seminarium', 'course' and 'training'.

add_action( 'woocommerce_before_shop_loop', 'eventsTerms', 18);
function eventsTerms() {

  $term = get_term_by('name', 'events', 'product_cat');
  $term_id = $term->term_id;
  $taxonomyName = 'product_cat';
  $termChildren = get_term_children( $term_id, $taxonomyName );

foreach ( $termChildren as $child ) {
  $_term = get_term_by( 'id', $child, $taxonomyName );
  $childTerms= ', "' . '' . $_term->name . '"';

  echo $childTerms; // only to see is ok

}

    if ( is_product_category( array("events", $childTerms) ) ) {
    global $product;
    wp_list_categories( 
      array(
          'show_option_all' => 'show all',
          'taxonomy' => 'product_cat',
          'style' => 'none',
          'separator' => '',
          'hide_empty' => 0,
      ));

  }

}

$childTerms returns all child categories names, so I want to use is_product_category conditional tag with array, but my code still works only on main category "events".

Where's the bug?

EDIT 1

Ok, I thought the reason why it's not working is implode can't be using in is_product_category() args. So I was trying with json_encode like that:

add_action( 'woocommerce_before_shop_loop', 'eventsTerms', 18);
function eventsTerms() {

  $term = get_term_by('name', 'events', 'product_cat');
  $term_id = $term->term_id;
  $taxonomyName = 'product_cat';
  $termChildren = get_term_children( $term_id, $taxonomyName );

foreach ( $termChildren as $child ) {
  $_term = get_term_by( 'id', $child, $taxonomyName );
  $childTerms[] = " '".$_term->name."'";
}

$x = implode(",", $childTerms);

$y = json_encode($x);

echo $y; // output as " 'seminarium', 'course', 'training'"

$y2 = preg_replace('/"([a-zA-Z]+[a-zA-Z0-9_]*)":/','$1:', $x); // removing qutes by preg_replace

echo $y2; // output as 'seminarium', 'course', 'training'

    if ( is_product_category( array('events', $y) ) ) {
    global $product;
    wp_list_categories( 
      array(
          'show_option_all' => 0,
          'taxonomy' => 'product_cat',
          'style' => 'none',
          'separator' => '',
          'hide_empty' => 0,
          'child_of' => $term_id,
      ));

  }

}
1

1 Answers

0
votes

The function get_term_by() doesn't work with "id", but with "term_id" instead (or "slug" or "name").
The function get_term_children() gives an array of Terms IDs.
The conditional function is_product_category() accepts an array of term names, slugs or Ids, as it's based on is_tax() function.

You are making things more complicated than they should be and you don't need a foreach loop.

To target a specific product category and its related children:

1) On Archive pages:

$term_slug = 'events';
$taxonomy  = 'product_cat';

$term_id   = get_term_by( 'slug', $term_slug, $taxonomy )->term_id; // Get the term ID
$child_ids = get_term_children( $term_id, $taxonomy ); // Get the children terms IDs
$terms_ids = array_merge( $child_ids, array($term_id) ); // an array of all term IDs (main term Id and it's children)

if ( is_product_category( $terms_ids ) ) {
    // Do something
}

So in you code:

add_action( 'woocommerce_before_shop_loop', 'eventsTerms', 18 );
function eventsTerms() {
    $term_slug = 'events';
    $taxonomy  = 'product_cat';

    $term_id   = get_term_by( 'slug', $term_slug, $taxonomy )->term_id; // Get the term ID
    $child_ids = get_term_children( $term_id, $taxonomy ); // Get the children terms IDs
    $terms_ids = array_merge( $child_ids, array($term_id) ); // an array of all term IDs (main term Id and it's children)

    if ( is_product_category( $terms_ids ) ) {
        global $product;
        
        wp_list_categories( array(
            'show_option_all' => 'show all',
            'taxonomy'        => 'product_cat',
            'style'           => 'none',
            'separator'       => '',
            'hide_empty'      => 0,
            'child_of'        => $term_id,
        ) );
    }
}

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


2) On product pages, cart items or order items (instead of archive pages):

You will use conditional function has_term(), that accepts also an array of term names, slugs or Ids (The third argument (optional) is the post ID or the product ID for WooCommerce products):

$term_slug = 'events';
$taxonomy  = 'product_cat';

$term_id   = get_term_by( 'slug', $term_slug, $taxonomy )->term_id; // Get the term ID
$child_ids = get_term_children( $term_id, $taxonomy ); // Get the children terms IDs
$terms_ids = array_merge( $child_ids, [$term_id] ); // an array of all term IDs (main term Id and it's children)

if ( has_term( $terms_ids, $taxonomy, $product_id ) ) {
    // Do something
}