0

I am having an issue and not able to resolve it.

// get list of categories
$terms = $listing->get_field( 'region' );

foreach($terms as $t){
    $parent_category = mg_get_term_parents( $t->term_id, 'region' );
}

When I dump parent_category I get an array (it prints only grandparent and parent) for child code is at the bottom.

array(2) {
  [0]=>
  object(WP_Term)#6446 (10) {
    ["term_id"]=>
    int(213)
    ["name"]=>
    string(8) "Americas"
    ["slug"]=>
    string(8) "americas"
    ["term_group"]=>
    int(0)
    ["term_taxonomy_id"]=>
    int(213)
    ["taxonomy"]=>
    string(6) "region"

  }
  [1]=>
  object(WP_Term)#6448 (10) {
    ["term_id"]=>
    int(157)
    ["name"]=>
    string(13) "United States"
    ["slug"]=>
    string(13) "united-states"
    ["term_group"]=>
    int(0)
    ["term_taxonomy_id"]=>
    int(157)
    ["taxonomy"]=>
    string(6) "region"   
  }
}

or I get an array if grandparent is not presented.

object(WP_Term)#6454 (10) {
  ["term_id"]=>
  int(214)
  ["name"]=>
  string(4) "EMEA"
  ["slug"]=>
  string(4) "emea"
  ["term_group"]=>
  int(0)
  ["term_taxonomy_id"]=>
  int(214)
  ["taxonomy"]=>
  string(6) "region"
}

If I have only parent and child, I use the following and it gives me good results. But not sure what needs to be added here to cover all cases.

foreach( $terms as $t )
{
    if ( $parent_category = mg_get_term_parents( $t->term_id, 'region' ) )
    {
        array_unshift( $terms, $parent_category );
    }
}


$formatted_terms = array_filter( array_map( function( $term ) {
    if ( ! $term = \MyListing\Src\Term::get( $term ) ) {
        return false;
    }

        return [
        'link' => $term->get_link(),
        'name' => $term->get_name(),
        'color' => $term->get_color(),
        'text_color' => $term->get_text_color(),
        'icon' => $term->get_icon( [ 'background' => false, 'color' => false] ),
        ];

    }, $terms ) );

The problem occurs when I have grandparent, parent, and child. The solution above doesn't work.

If I use

$formatted_terms = array_filter( array_map( function( $term ) {
        if ( ! $term = \MyListing\Src\Term::get( $term ) ) {
            return false;
        }

            return [
            'link' => $term->get_link(),
            'name' => $term->get_name(),
            'color' => $term->get_color(),
            'text_color' => $term->get_text_color(),
            'icon' => $term->get_icon( [ 'background' => false, 'color' => false] ),
            ];

        }, $terms ) );

I print only 1 region from the array and the one that is missing which is a child. Array outputs only parent and grandparent. I need to add array output somehow to the code above tog et all needed.

Any idea how to accomplish this?

Marko
  • 101
  • 1
  • 1
  • 9

1 Answers1

0

In order to work through arrays nested in arrays nested in arrays (ad infinitum…) you will either need to handle each with a loop, or build a Recursive Function that does it for you.

I'm currently the lead engineer on a site that relies heavily on custom taxonomy and term structures. Here's a simple function I use to build a fully hierarchical array of taxonomy terms:

function hierarchical_term_list( Array &$terms, Array &$into, $parent_id = 0 ){
    foreach( $terms as $i => $term ){
        if( $term->parent == $parent_id ){
            $into[] = $term;
            unset($terms[$i]);
        }
    }

    foreach( $into as $top_term ){
        $top_term->children = array();
        hierarchical_term_list( $terms, $top_term->children, $top_term->term_id );
    }
}

Now, once I get my term list:

$terms = get_terms(array(
    'hide_empty' => true,
    'taxonomy'   => 'some_tax',
    'post_type'  => 'some_post_type'
));

$hierarchy = array();
hierarchical_term_list( $terms, $hierarchy );

This gives me a neat array of WP_Term objects like so (truncated for brevity)

array(2) {
    [0] => object(WP_Term)#1343 (12) {
        ["term_id"] => int(5)
        ["name"] => string(4) "Test"
            …
        ["children"] => array(1) {
            [0] => object(WP_Term)#1344 (12) {
                ["term_id"] => int(16)
                ["name"] => string(10) "Test Child"
                    …
                ["children"] => array(2) {
                    [0] => object(WP_Term)#1345 (12) {
                        ["term_id"] => int(17)
                        ["name"] => string(16) "Test Grand Child"
                        ["slug"] => string(16) "test-grand-child"
                           …
                        ["children"] => array(0) {}
                    }
                    [1] => object(WP_Term)#1346 (12) {
                        ["term_id"] => int(18)
                        ["name"] => string(20) "Favorite Grand Child"
                        ["slug"] => string(20) "favorite-grand-child"
                           …
                        ["children"] => array(0) {}
                    }
                }
            }
        }
    }
    [1] => object(WP_Term)#1347 (12) {
        ["term_id"] =>int(1)
        ["name"] => string(13) "Childless"
        ["slug"] => string(13) "childless"
            …
        ["children"] => array(0) {}
    }
}

Now to the important part - how do you ouput these arrays in arrays in arrays in arrays… This is where the Recursive Function I mentioned above comes in to play.

First, we then need to pass our hierarchical array to the function as an argument, and then if there are children in it, call itself again, instead using the child array as an argument. This will continue all the way down until there are no more children, at which point it will "go back upwards" in recursion depth, until it gets to the next term, at the closest level that it hasn't dealt with yet.

Here's a simplified version of the function I use:

function output_hierarchical_term_list( $terms ){
    echo '<ul class="hierarchical-terms">';
        foreach( $terms as $term ){
            printf( '<li>%s', $term->name );
                if( !empty( $term->children ) ){
                    output_hierarchical_term_list( $term->children );
                }
            echo '</li>';
        }
    echo '</ul>';
}

That will output something similar to the following:

<ul class="hierarchical-terms">
    <li>
        <strong>Test</strong>
        <ul class="hierarchical-terms">
            <li>
                <strong>Test Child</strong>
                <ul class="hierarchical-terms">
                    <li><strong>Test Grand Child</strong></li>
                    <li><strong>Favorite Grand Child</strong></li>
                </ul>
            </li>
        </ul>
    </li>
    <li>
        <strong>Childless</strong>
    </li>
</ul>

Hopefully that helps!

Xhynk
  • 13,513
  • 8
  • 32
  • 69