WordPress.org

Support

Support » WP-Advanced » Get Tags specific to Category

Get Tags specific to Category

  • I’ve noticed there is no native way to retrieve tags based on the category. I’ve seen a few plugins that do something similar but don’t this. There have also been been a few snippets posted that kinda do it but either show duplicates of tags, or seem too labor intensive.

    In short has anyone done a db query as follows:

    select category
    from category select posts
    from posts select post tags
    make array of unique post tags (id, name, slug)

    I’ve started playing with the query function but as I’m learning and shooting in dark.

    Any help, even a quick tut on how to run a query would be helpful.

Viewing 15 replies - 1 through 15 (of 37 total)
  • Bump, exactly what I’m looking for too. I want to grab the Meta data from multiple posts in one category, then loop it out nicely at the bottom of a page/in a sidebar etc.

    Any friendlies out there?

    OK, this is what i have done, much more basic than i thought:

    <ul>
    <?php global $post;
    		     $myposts = get_posts('numberposts=-1&offset=0&category=13&order=DESC');
    		     foreach($myposts as $post) :
    	?>
    	<li>
        <?php if(get_post_meta($post->ID, 'Event Name', true)): ?><?php echo get_post_meta($post->ID, 'Event Name', true); ?><br /><?php endif; ?>
    	<?php if(get_post_meta($post->ID, 'Event Location', true)): ?><?php echo get_post_meta($post->ID, 'Event Location', true); ?><br /><?php endif; ?>
        <?php if(get_post_meta($post->ID, 'Event Date Day', true)): ?><?php echo get_post_meta($post->ID, 'Event Date Day', true); ?><br /><?php endif; ?>
        <?php if(get_post_meta($post->ID, 'Event Date Month', true)): ?><?php echo get_post_meta($post->ID, 'Event Date Month', true); ?><br /><?php endif; ?>
        <?php if(get_post_meta($post->ID, 'Event Date Year', true)): ?><?php echo get_post_meta($post->ID, 'Event Date Year', true); ?><br /><?php endif; ?>
        <?php if(get_post_meta($post->ID, 'Event Time', true)): ?><?php echo get_post_meta($post->ID, 'Event Time', true); ?><br /><?php endif; ?>
    	</li>
    	<?php endforeach; ?>
    </ul>

    Hopefully this will help someone.

    Electric Studio, that’s not exactly what I was looking for but it was good stepping stone.

    <?php
    	query_posts('category_name=work');
    	if (have_posts()) : while (have_posts()) : the_post();
            $posttags = get_the_tags();
    		if ($posttags) {
    			foreach($posttags as $tag) {
    				$all_tags_arr[] = $tag -> name; //USING JUST $tag MAKING $all_tags_arr A MULTI-DIMENSIONAL ARRAY, WHICH DOES WORK WITH array_unique
    			}
    		}
    	endwhile; endif; 
    
    	$tags_arr = array_unique($all_tags_arr); //REMOVES DUPLICATES
    	echo '<pre>'.print_r($tags_arr, true).'</pre>'; //OUTPUT FINAL TAGS FROM CATEGORY
    
    ?>

    This does the job, except it would be nice to have $tags_arr as a multi-dimensional array but that does work with array_unique.

    Still my question is, if you have say 100 posts in a category, is doing query like this the most efficient way of getting these results.

    I too would like to find a more elegant solution to this.

    I’d probably write the query from scratch. query_posts is pulling a lot of data you don’t need. But that’s not a query for the faint of heart…

    So just to be clear the aim here is to grab post tags that exist for posts in one particular category?..

    I think we can proberly manage that.

    1. Grab IDs for all posts in particular category
    2. Grab post tags for each post
    3. Remove duplicates
    4. Display data

    I think what’s important is to not grab all post data when you only need the IDs.

    Give me a little while, i think i might be able to knock something up..

    Can someone just clarify if you need the posts or just the tags?..

    If you need the posts to, then you might aswell build array items for each post, then at the end of all the posts, the array is finished, just remove dupes, then display the data..

    If you don’t need posts, and just the post_tags, then this could be refined into a single stand-alone query, but if you’re grabbing posts to there’s no reason you can’t just build the array as you display each post.. which is what you’ve got posted above… except that you’ve used query_posts simply to loop over each post in that category, but then you don’t use any of the data, you’re simplying using it in order to run get_the_tags, which of course is a little inefficient.

    Do you want post data or simply just the tags and nothing but the tags? (which it looks like was the intention).

    This what I’ve come up with. I think apljdi, is right about custom query. This still seems a bit excessive.

    <?php
            $project_query = query_posts('category_name=projects');
            while (have_posts()) : the_post();
                $posttags = get_the_tags();
                if ($posttags) {
                    foreach($posttags as $tag) {
                        $all_tags_arr[] = $tag -> name; //USING JUST $tag MAKING $all_tags_arr A MULTI-DIMENSIONAL ARRAY, WHICH DOES WORK WITH array_unique
                    }
                }
            endwhile;
        ?>
        <?php if ( is_array($all_tags_arr) && count($all_tags_arr) > 0 ): ?>
    <?php
        $tags_arr = array_unique($all_tags_arr); //REMOVES DUPLICATES
        foreach( $tags_arr as $tag ):
            $el = get_term_by('name', $tag, 'post_tag');
    		$arr[] = '"tag-'.$el->slug.'"';
        ?>
        <span><a href="#<?php echo $el->slug; ?>" id="taglink-tag-<?php echo $el->slug; ?>" rel="tag-<?php echo $el->slug; ?>"><?php echo $el->name; ?></a> <span class="slash">//</span></span>
    <?php endforeach; ?>

    The goal of this was to be able to batch tags based on the category to develop a category specific list of tags, which in turn linked to that tags filtered archive.

    I suppose the question is whether a get_results is more efficient then query_posts, if not then a custom joined query isn’t going to be mean anything at this point and refining what you have would be best…

    Of course get_results in theory should be lighter and quicker, so perhaps a query that joins the various fields together will give the best results, but i’ll have to spend some time looking over the tables (figure out the joins – mysql is not my strong suit).

    I’ll see if i can write the query for you when i get some time to test it…. joins are a hair puller… lol..

    Wow this is a tricky one, post_tags and categories sit in the same table…

    Just trying to get the query right first, here’s what i have so far if anyone thinks they can help (just in phpmyadmin until i have the right query).

    SELECT DISTINCT wp_posts.ID, wp_term_taxonomy.*, wp_terms.*
    FROM wp_posts, wp_term_relationships, wp_term_taxonomy
    JOIN wp_terms ON wp_term_taxonomy.term_taxonomy_id = wp_terms.term_id
    WHERE wp_posts.ID = wp_term_relationships.object_id
    AND wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
    AND wp_term_taxonomy.taxonomy = 'post_tag'
    LIMIT 0 , 300

    Anyone spot any immediate problems? .. Of course i’m still working on figuring out how to ensure posts match a set category, it’s taken me a little while to get this far, not bad for a single query..

    Query took 0.0065 sec

    Mind you only 30 results on my install, but nice and fast, just need to figure out the rest of the query…

    Could really do with some help from someone who’s written joins before. The above WHERE’s act as JOINS, but i put a regular JOIN in to… it’s a little beyond me if i’m to be frank, but i’ll give it a shot nonetheless…. 🙂

    The real killer is how to join up the statement when post tags and categories sit in the same table, i can’t quite wrap my head around how i can limit to one category, whilst still grabbing info on other entries in that very same table… ** just need a fresh set of eyes i think **

    This query seemed to work for me. In this case ‘Lectures’ is the name of the category and the column ‘tag’ will have all the tags in this category

    SELECT DISTINCT terms2.name as tag
    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.name = 'Lectures' AND
    	t2.taxonomy = 'post_tag' AND p2.post_status = 'publish'
    	AND p1.ID = p2.ID

    Perfect example, thank you kelsey…

    Clearly someone who knows their joins.. 😉 Worked flawlessly first time..

    excellent work kelseydamas
    thank you for it

    Great code input everyone, it’s exactly what I needed for a WP I’m working on. I took it a bit further, perhaps someone who hasn’t implemented will find this useful.

    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;
Viewing 15 replies - 1 through 15 (of 37 total)
  • The topic ‘Get Tags specific to Category’ is closed to new replies.
Skip to toolbar