Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get all tags based on specific category (including all tags from child categories and posts) wordpress

Tags:

wordpress

tags

I wanted to use wp_tag_cloud() on single.php using the argument that gets all tags from specific category including all tags from its child categories and posts.

like image 228
Chintan Bhatt Avatar asked Apr 01 '14 13:04

Chintan Bhatt


2 Answers

In your theme's functions.php insert the following function:

function get_category_tags($args) {
    global $wpdb;
    $tags = $wpdb->get_results
    ("
        SELECT DISTINCT terms2.term_id as tag_id, terms2.name as tag_name, null as tag_link
        FROM
            wp_posts as p1
            LEFT JOIN wp_term_relationships as r1 ON p1.ID = r1.object_ID
            LEFT JOIN wp_term_taxonomy as t1 ON r1.term_taxonomy_id = t1.term_taxonomy_id
            LEFT JOIN wp_terms as terms1 ON t1.term_id = terms1.term_id,

            wp_posts as p2
            LEFT JOIN wp_term_relationships as r2 ON p2.ID = r2.object_ID
            LEFT JOIN wp_term_taxonomy as t2 ON r2.term_taxonomy_id = t2.term_taxonomy_id
            LEFT JOIN wp_terms as terms2 ON t2.term_id = terms2.term_id
        WHERE
            t1.taxonomy = 'category' AND p1.post_status = 'publish' AND terms1.term_id IN (".$args['categories'].") AND
            t2.taxonomy = 'post_tag' AND p2.post_status = 'publish'
            AND p1.ID = p2.ID
        ORDER by tag_name
    ");
    $count = 0;
    foreach ($tags as $tag) {
        $tags[$count]->tag_link = get_tag_link($tag->tag_id);
        $count++;
    }
    return $tags;
}

In your theme document call the function as follows. Notice it accepts multiple category id's:

 $args = array(
        'categories'                => '12,13,14'
    );

$tags = get_category_tags($args);

This will return an array that you could do the following with:

$content .= "<ul>";
foreach ($tags as $tag) {
    $content .= "<li><a href=\"$tag->tag_link\">$tag->tag_name</a></li>";
}
$content .= "</ul>";
echo $content;
like image 100
Narendra Avatar answered Oct 27 '22 01:10

Narendra


There is no native way in Wordpress to do this. The reason being that tags are not tied to categories, they are separate. That being said, the only way to get all tags IN USE by a specific category is to cycle through every post of the category and grab the tags of each post.

I've written up a quick function to do just that.

Place this function into your functions.php file.

function get_tags_in_use($category_ID, $type = 'name'){
    // Set up the query for our posts
    $my_posts = new WP_Query(array(
      'cat' => $category_ID, // Your category id
      'posts_per_page' => -1 // All posts from that category
    ));

    // Initialize our tag arrays
    $tags_by_id = array();
    $tags_by_name = array();
    $tags_by_slug = array();

    // If there are posts in this category, loop through them
    if ($my_posts->have_posts()): while ($my_posts->have_posts()): $my_posts->the_post();

      // Get all tags of current post
      $post_tags = wp_get_post_tags($my_posts->post->ID);

      // Loop through each tag
      foreach ($post_tags as $tag):

        // Set up our tags by id, name, and/or slug
        $tag_id = $tag->term_id;
        $tag_name = $tag->name;
        $tag_slug = $tag->slug;

        // Push each tag into our main array if not already in it
        if (!in_array($tag_id, $tags_by_id))
          array_push($tags_by_id, $tag_id);

        if (!in_array($tag_name, $tags_by_name))
          array_push($tags_by_name, $tag_name);

        if (!in_array($tag_slug, $tags_by_slug))
          array_push($tags_by_slug, $tag_slug);

      endforeach;
    endwhile; endif;

    // Return value specified
    if ($type == 'id')
        return $tags_by_id;

    if ($type == 'name')
        return $tags_by_name;

    if ($type == 'slug')
        return $tags_by_slug;
}

Then when you want to grab the tags of a specific category, call this function like so:

// First paramater is the category and the second paramater is how to return the tag (by name, by id, or by slug)
// Leave second paramater blank to default to name

$tags = get_tags_in_use(59, 'name');

Hope this helps.

EDIT:

This is the function you will need to use in conjunction with the other:

function tag_cloud_by_category($category_ID){
    // Get our tag array
    $tags = get_tags_in_use($category_ID, 'id');

    // Start our output variable
    echo '<div class="tag-cloud">';

    // Cycle through each tag and set it up
    foreach ($tags as $tag):
        // Get our count
        $term = get_term_by('id', $tag, 'post_tag');
        $count = $term->count;

        // Get tag name
        $tag_info = get_tag($tag);
        $tag_name = $tag_info->name;

        // Get tag link
        $tag_link = get_tag_link($tag);

        // Set up our font size based on count
        $size = 8 + $count;

        echo '<span style="font-size:'.$size.'px;">';
        echo '<a href="'.$tag_link.'">'.$tag_name.'</a>';
        echo ' </span>';

    endforeach;

    echo '</div>';
}

So you can use this function simply like so:

tag_cloud_by_category($cat_id);
like image 32
Joel Worsham Avatar answered Oct 27 '22 01:10

Joel Worsham