2

I want to show a category only if a (custom) post is in that category AND region = $name for that post.

So, e.g. I have a custom post (type "business") named "Mamma Mia" in child-category: "pizzerias" (and in parent-category "food"), and in region "Rotterdam" (custom taxonomy: "region", custom taxonomy term: "rotterdam").

=> display category "pizzerias" (and parent-category "food")

Only, I have no clue how to accomplish this. I'd appreciate any help on this puzzle.

<?php 

// $filter = array('region'=>$name); 

$categories = get_categories(); 
foreach ($categories as $cat) 
{ 
    if($cat->parent < 1) 
    { 
    $cat_name = $cat->cat_name; 
    $catid = get_cat_ID( $cat_name ); 
    echo $cat_name. '<br/>'; 

    $args=array( 
      'orderby' => 'name', 
      'order' => 'ASC', 
      'child_of' => $catid 
      ); 
    $categories=get_categories($args); 
      foreach($categories as $category) {  
        echo '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . '>' . $category->name.'</a><br/>'; 
        }  

    } 
} 

// print_r($categories);  


?>
3
  • So you want to list category terms that have business es assigned which are also assigned specific region?
    – Rarst
    Dec 6, 2010 at 13:04
  • @Henk, can you explain a little further where you'd like to do this? On a single post page? On a taxonomy archive? On a category archive? Dec 6, 2010 at 13:30
  • I think we can generalize this to faceted search. There is a plugin with this name, but it seems you can't combine multiple taxonomies. Because this is so interesting, I added the bounty.
    – Jan Fabry
    Dec 6, 2010 at 14:47

8 Answers 8

2
+50

the intention is to show a list of categories, but only those categories that have posts where the custom taxonomy region is set to Rotterdam

This is done in the Query Multiple Taxonomies plugin:

http://plugins.trac.wordpress.org/browser/query-multiple-taxonomies/trunk/core.php?rev=308185#L10

1
  • 1
    And more specifically, in its drill-down navigation widget. Great! Now this only should be extended to show the parent categories too: if a post is attached to Pizzerias I also see it when I browse Food, but Food is not shown in the widget if the post is not explicitly attached to it.
    – Jan Fabry
    Dec 8, 2010 at 7:27
1

General idea - query for specific set of posts, gather all of their categories, filter, let function beat them in shape.

Generic code:

$posts = get_posts(array(
    'tag' => 'linux'
));

$categories = array();

foreach( $posts as $post ) {

    $cats = get_the_category($post->ID);

    foreach($cats as $c)
        $categories[] = $c->term_id;
}

$categories = array_unique($categories);
sort($categories);
$categories = implode(',', $categories);

$result = get_categories(array(
    'include' => $categories
));

Issues are - as I remember decent queries for multiple taxonomies will only come in WP 3.1 and this might get very intensive so will take caching (probably for each region).

3
  • How does the include parameter affect hierarchical results? If there are some posts in Pizzerias, but none directly attached to its parent Food, will Food be displayed? Or are posts automatically attached to parent categories too?
    – Jan Fabry
    Dec 6, 2010 at 14:24
  • @Jan Fabry tested, if only child category id is passed to get_categories() then parent category is not retrieved. :( So one more step would be to loop through categories and get parents. Even larger mess.
    – Rarst
    Dec 6, 2010 at 14:34
  • I think we should look in the direction of a custom SQL query, joining multiple taxonomy tables. And caching, indeed.
    – Jan Fabry
    Dec 6, 2010 at 14:41
1

On the version of wordpress I'm using which is version 3.1.2. If you were to add 'taxonomy' => 'taxonomy_term' to the array of args it should work. So here's a modification to your original code to include the taxonomy in the array. Don't know the taxonomy name you're trying to use or not though:

<?php 

// $filter = array('region'=>$name); 

$categories = get_categories(); 
foreach ($categories as $cat) 
{ 
    if($cat->parent < 1) 
    { 
    $cat_name = $cat->cat_name; 
    $catid = get_cat_ID( $cat_name ); 
    echo $cat_name. '<br/>'; 

    $args=array( 
      'taxonomy' => 'taxonomy_term', 
      'orderby' => 'name', 
      'order' => 'ASC', 
      'child_of' => $catid 
      ); 
    $categories=get_categories($args); 
      foreach($categories as $category) {  
        echo '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . '>' . $category->name.'</a><br/>'; 
        }  

    } 
} 

// print_r($categories);  
?>
1

I've adapted @rarst's answer from above to use 3 custom taxonomies. I only want to spit out the terms that are attached to one or more of the posts in the loop.

Here's my function that I've added to functions.php:

function dv_setup_sidebar_cats() {
    global $wp_query;

    $designers = array();
    $sizes     = array();
    $colors    = array();

    foreach( $wp_query->posts as $post ) {

        $des   = get_the_terms($post->ID, 'designer');
        $siz   = get_the_terms($post->ID, 'size');
        $col   = get_the_terms($post->ID, 'color');    

        foreach($des as $d) {
            $designers[] = $d->term_id;
        }

        foreach($siz as $s) {
            $sizes[] = $s->term_id;
        }

        foreach($col as $c) {
            $colors[] = $c->term_id;
        }

    }

    if ( !empty($designers) ) {
        $designers = array_unique($designers);
        sort($designers);
        $designers = implode(',', $designers);

        $dresult   = get_categories(array(
            'include'  => $designers,
            'taxonomy' => 'designer'
        ));
    }

    if ( !empty($sizes) ) {
        $sizes = array_unique($sizes);
        sort($sizes);
        $sizes = implode(',', $sizes);

        $sresult   = get_categories(array(
            'include'  => $sizes,
            'taxonomy' => 'size'
        ));
    } 

    if ( !empty($colors) ) {
        $colors = array_unique($colors);
        sort($colors);
        $colors = implode(',', $colors);

        $cresult   = get_categories(array(
            'include'  => $colors,
            'taxonomy' => 'color'
        ));
    }

    $return = array(
        'size'     => $sresult,
        'color'    => $cresult,
        'designer' => $dresult
    );


    return $return;

}

Hope this helps someone else.

-J

0

Forgive me if I've missed something, but would it not be as simple as;

if (is_object_in_term($post->ID, 'region', 'rotterdam'))
    the_category(); // displays categories associated with current post

In the admin, are you attaching the post to both 'pizzerias' and 'food' (by ticking both checkboxes), or just 'pizzerias'?

If the latter, the_category() won't show 'Food' by default, so you'll have to grab the category hierarchy yourself.

3
  • No, the intention is to show a list of categories, but only those categories that have posts where the custom taxonomy region is set to Rotterdam. This question was also asked on SO, by the way.
    – Jan Fabry
    Dec 6, 2010 at 11:28
  • Unless I am misunderstanding this seems like a fitting answer. If Mamma Mia is pizzeria in rotterdam then by definition there are pizzerias in rotterdam and category should be displayed. Otherwise I don't understand how category is supposed to be connected to region.
    – Rarst
    Dec 6, 2010 at 12:11
  • @Rarst: The way I understood the question is that the category list should not be shown just on a post page, but for example on region/rotterdam/: for all posts that use this custom taxonomy term, give me one tree of all categories they are attached too. The OP uses get_categories(), which is not limited to the categories of the current post.
    – Jan Fabry
    Dec 6, 2010 at 12:48
0

you can return the taxonomie for custom post with a small funtion:

    function get_the_taxonomy( $taxonomy, $id = FALSE ) {
        global $post;

        $id = (int) $id;
        if ( !$id )
            $id = (int) $post->ID;

        $categories = get_object_term_cache( $id, $taxonomy );
        if ( FALSE === $categories ) {
            $categories = wp_get_object_terms( $id, $taxonomy );
            wp_cache_add($id, $categories, $taxonomy . '_relationships');
        }

        if ( !empty( $categories ) )
            usort( $categories, '_usort_terms_by_name' );
        else
            $categories = array();

        foreach ( (array) array_keys( $categories ) as $key ) {
            _make_cat_compat( $categories[$key] );
        }

        return $categories;
    }

Also you can use the function of wp-core:

$taxonomys = get_the_term_list($id, YOUR_CUSTOM_POST_TYPE, '', ', ', '' );

and you can ask for tax with is_tax(), see codex for this conditional tag

Maybe this helps, when i understand your problem right. Sorry for my bad english.

2
  • I think Henk Jan wants to get a list of categories, independent from a current post. Just all categories that have posts in them assigned to the custom term rotterdam.
    – Jan Fabry
    Dec 6, 2010 at 22:41
  • Thanks for hint; i think it possible to use a custom query with the custom term. The post give back all terms, and the query must use all or the first term to list in the loop all post to this term. Also it is possible to return all categories to the posts in thuis query.
    – bueltge
    Dec 7, 2010 at 8:11
0

Thank you all for helping me out - that's really great. I'd like to share with you what I've come up with. I know it is not the smartest solution. The drawback is that a parent category is shown for a region, when there is no custom post attached to it for this region (but there is a custom post attached to it for an other region).

I am using this on a region (taxonomy archive) page.

<?php
$categories = get_categories();
foreach ($categories as $cat)
{
    if($cat->parent < 1)
    {
        $cat_name = $cat->cat_name;                         
        $catid = get_cat_ID( $cat_name );

        echo '<div class="indexcolumn-top">';

        $img = $taxonomy_images_plugin->get_image_html( 'fullsize', $cat->term_taxonomy_id );
        if( !empty( $img ) )
            print $img;
        else 
            echo '<h2>' .$cat_name. '</h2>';

        $input = array();
        $args=array(
          'child_of' => $catid,
          'orderby' => 'name',
          'order' => 'ASC'
          );

        $categories = get_categories($args);
        foreach ($categories as $cat)
        {
            $cat_name = $cat->cat_name;
            $catid = get_cat_ID( $cat_name );

            $args = array(
                'post_status' => 'publish',
                'taxonomy_name' => 'region',
                'taxonomy_term' => $name,
            );
            $custom_posts = get_posts_by_taxonomy($args);
            if ($custom_posts):
                foreach ($custom_posts as $post):
                    setup_postdata($post);
                    $postcategory = get_the_category(); $postcat = $postcategory[0]->cat_name;
                    if ($postcat == $cat_name):
                        $category = get_the_category(); 
                        $input[] = $catid;
                    endif;
                endforeach;
            endif;
        }
        echo '<br/>';
        $output = array_unique($input);
        if (empty($output)):
            echo '<p>Geen bedrijven</p>';
            echo '</div>';
        else :
            echo '<ul class="port-box">';
            foreach ($output as $output) {
                $cat_name = get_cat_name($output);  
                echo '<li><a href="' . get_category_link($output) . '" title="' . sprintf( __( "View all posts in %s" ), $cat_name ) . '" ' . '>' . $cat_name .'</a></li>';                             
            }
            echo '</ul></div>';
        endif;
    }                                                   
}
?>
4
  • 1
    I don't think this is an efficient way to do it: you do a lot of queries, and I don't understand the inner post loop: if a post is found in the current category, you can probably just add that category to the list without looping through all the posts?
    – Jan Fabry
    Dec 8, 2010 at 12:58
  • @Jan: I know it is not the smartest solution. I don't understand your remark about the inner post loop though. You'll need the inner post loop to find a match - or not. Or, can you quit the loop in case of hit? But, how would you do that then?
    – Henk Jan
    Dec 8, 2010 at 14:32
  • Nevermind, I thought your get_posts_by_taxonomy() function selected both by taxonomy and category. The following question is why you repeat this query over and over, instead of doing it once and re-using the results. And why check only the first category? If a business is in both Pizzeria and French Fries, only one of them will be returned, so you possible miss one in the end.
    – Jan Fabry
    Dec 8, 2010 at 14:45
  • @Jan: OK. I am only checking the first category because my businesses can be in one category only. I don't get your first question. The if ($custom_posts): endif; can be dropped. But, you'll need to loop to find a match - or not. What do you mean with reusing?
    – Henk Jan
    Dec 8, 2010 at 15:20
0
<?php $cat_id = $_GET["cat"];?>     
      <li id="category-active"><a><?php if ($cat_id){echo get_the_category_by_id($li_id);}else{ echo "Selectedcategory";}?></a></li>            <?php   $subcategories1 = wp_list_categories("title_li&child_of=$cat_id&hide_empty");
                wp_list_categories("title_li=&current_category="); ?>
                    </ul><?php ?>

thanks for your help.

but i think their is no need of foreach or any loop we can get child of any category by using this simple code first $li_id get the current cat id and we dynamicaly passed this id to child_of=$cat_id and it show the selected cat childs i am using it in my site side bar.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.