Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

How to show only parent terms with get_the_term_list() shortcode WordPress

  • SOLVED

Hi, I have this shortcode:

function post_taxonomy_sc( $atts ) {
$defaults = [
'post_id' => get_the_id(),
'taxonomy' => 'category',
'before' => '',
'sep' => ', ',
'after' => '',
'linked' => 'yes',
];

$atts = shortcode_atts($defaults, $atts, 'post_taxonomy');

if($atts['linked'] == 'yes'){
$terms = get_the_term_list($atts['post_id'], $atts['taxonomy'], $atts['before'], $atts['sep'], $atts['after']);
}
else {
$terms = strip_tags(get_the_term_list($atts['post_id'], $atts['taxonomy'], $atts['before'], $atts['sep'], $atts['after'] ));
}
return "<span class=\"post-taxonomy-terms-sc\">" . $terms . "</span>";
}
add_shortcode( 'post_taxonomy', 'post_taxonomy_sc' );


When used, I can output a list of taxonomy terms based on a specific taxonomy for a specific post.

As an example, I have a custom taxonomy called "Payout Options" with terms like "PayPal", "Payoneer", and "Gift cards".

The shortcode would output something like this: "PayPal, Gift cards, Payoneer" (if those terms were selected for a post)

This is where I'm having problems:

The "Gift cards" term has child terms like "Amazon gift cards" and "Walmart gift cards"

If the Gift cards term exists on a post along with "Amazon gift cards" and "Walmart gift cards", I want the shortcode to only output "Gift cards" ignoring the child terms. Is this possible? How would I do this?

I would also settle for being able to output like this: "Gift cards (Amazon gift cards, Walmart gift cards), PayPal, Payoneer" because at the moment it outputs in alphabetical order and looks very weird.

Hope this makes sense! Thank you.

Answers (2)

2021-08-13

Cesar Contreras answers:

Yry using the get_terms () function instead and use the list of terms as you wish.
this is the documentation: https://developer.wordpress.org/reference/functions/get_terms/

If parent => 0 is passed, only top-level terms will be returned
$terms = get_terms( array(
'taxonomy' => 'tax_name',
'parent' => 0
) );


Swift comments:

Same as below, a problem I've run into with get_terms() is that it doesn't allow a post ID attribute.


Cesar Contreras comments:

Then with the function get_the_terms()
https://developer.wordpress.org/reference/functions/get_the_terms/

this functions return A WP_Term object,
object(WP_Term) (11) {
["term_id"]=> //int
["name"]=> //string
["slug"]=> //string
["term_group"]=> //int
["term_taxonomy_id"]=> //int
["taxonomy"]=> //string
["description"]=> //string
["parent"]=> //int
["count"]=> // int
["filter"]= //string
["meta"]= array(0) {} //an array of meta fields.


Then only add the condition if($term->parent !== 0) if you need to know if it is a parent category


Swift comments:

Ok, any idea of how this would be incorporated into the shortcode I have to output a comma-separated list of the parent terms?


Cesar Contreras comments:

According to your code, the following would apply:

$parentTerms = array();
$terms = get_the_terms( $atts['post_id'], $atts['taxonomy']);
foreach ($terms as $term) {
if ( '0' == $term->parent ) {
array_push($parentTerms, $term);
}
}
$stringParentTermsName = $atts['before'] . join($atts['sep'], wp_list_pluck($parentTerms, 'name')) . $atts['after'];


Swift comments:

This works beautifully for a non-hyperlinked comma-separated list. Thank you!

Is there any way to incorporate the "linked" attribute so that if it's set to "yes" each taxonomy term is linked to its appropriate archive?


Cesar Contreras comments:

//define array to save the name or link of the parent terms
$parentTerms = array();
//get all the terms for the current post
$terms = get_the_terms( $atts['post_id'], $atts['taxonomy']);
//if the linked option is true
if($atts['linked'] == 'yes'){
//we go through the array of terms
foreach ($terms as $term) {
//if the curent term is parent
if ( '0' == $term->parent ) {
//create the link for add to the parentTerms array
$linkTerm = '<a href="' . esc_url( get_term_link( $term->slug, $atts['taxonomy'] ) ) . '">' . esc_html( $term->name ) . '</a>';
//add the link of the term to the parentTerms array
array_push($parentTerms, $linkTerm );
}
}
}else{
//if the linked option is false, return only the name term
//we go through the array of terms
foreach ($terms as $term) {
//if the curent term is parent
if ( '0' == $term->parent ) {
//add the name of the term to the parentTerms array
array_push($parentTerms, $term->name);
}
}
}
//result. Create the OutPut result...
// add the before, ajoin our array parentTerms separated by the character defined in the attributes and add the after
$outParentTermsName = $atts['before'] . join($atts['sep'], $parentTerms) . $atts['after'];


Swift comments:

You're a genius!! Thank you so much.

As a side note, for some reason WordPress was showing an error on the post edit screen for the foreach loops (it was giving an "invalid argument supplied" error) but I just wrapped them in an "if (is_array($terms))" and the error went away.

2021-08-13

Monit Jadhav answers:

You can use the get_terms function in WordPress with "parent"=>0 attribute, it will return the term object then you can manipulate it with a for loop to get the desired output.

https://developer.wordpress.org/reference/functions/get_terms/




$terms= get_terms( array(
'taxonomy' => 'category',
'parent' => 0
) );

Term Object that is returned will look something like this

WP_Term Object
(
[term_id] =>
[name] =>
[slug] =>
[term_group] =>
[term_taxonomy_id] =>
[taxonomy] =>
[description] =>
[parent] =>
[count] =>
[filter] =>
)


foreach ($terms as $term) {
echo '<a href="'.get_category_link($term->ID).'">'.$term->name.'</a>, ';
}


You can loop through the terms to get the desired output as you desire

Thanks

Monit


Swift comments:

A problem I've run into with get_terms() is that it doesn't allow a post ID attribute. I need to be able to use the shortcode anywhere on my site to display any post's taxonomy terms (not just the current post).