WordPress.org

Ready to get started?Download WordPress

Forums

show 1 post in parent category (34 posts)

  1. amandach
    Member
    Posted 2 years ago #

    Hi,

    How can I show just 1 post in the parent category and all the other posts (excluding the one showing in the parent category) in the child category? I'm breaking my head trying to figure this out and need some help.

    Thanks

  2. Jacob Chappell
    Member
    Posted 2 years ago #

    Can you please give some more details? Is the only association these posts have the fact that their in the same category? What is the relevance of the single post in the parent category to the many posts in the child category? I assume you're using WP_Query for this.

  3. amandach
    Member
    Posted 2 years ago #

    So I'm actually using fold category list because I want a category tree but the php is totally customizable and you can also use wordpress codex to add args.

    I have 1 post that's in the parent category and then all other posts are in the child category only. Although the parent category is not checked off (just the child cats are) the posts are showing up when you click on the parent category.

    For example, in Post 1, Parent Cat 1 is checked off. Post 1 shows up in Parent Cat 1. Post 2 is in Child Cat 1 (child cat of Parent Cat 1) but it's showing up in Parent Cat 1 AND Child Cat 1. I need it to show up in Child Cat 1 ONLY not Parent Cat 1.

    Thanks for your help.

    Cheers,
    Amanda

  4. Jacob Chappell
    Member
    Posted 2 years ago #

    Hmm, I've never used the folder category list thing you speak of. Let me see if I understand your problem though (let me know if this isn't correct). You are viewing posts on a category listing page (something like yoursite.com/category/parent-cat-1). On that page you only want Post 1 to show up (the post that's directly in the parent-cat-1 category) but posts from it's child categories are also showing up?

    Would you happen to have some demo pages you could link to that demonstrate this?

  5. amandach
    Member
    Posted 2 years ago #

    Yes that's spot on! The site is on my localhost so I can't post :(
    Is there any arg that I can add to the codex that will make that work? Or it's more complicated?

    The fold category list isn't really relevant because I can add any custom php to that.

  6. Jacob Chappell
    Member
    Posted 2 years ago #

    I can only show you the WP_Query argument because that's what I use. You can exclude posts from a particular category. In this case, you'd want to exclude all posts from that child category.

    If Parent Cat 1 has a category ID of 1 and
    Child Cat 1 has a category ID of 2 then:

    'category__not_in' => array( 2 )

    would be the parameter for WP_Query. You can view the category parameters for WP_Query here.

    You could pass additional arguments to that array if you wanted to exclude other categories as well.

  7. amandach
    Member
    Posted 2 years ago #

    So there's no general rule that I can do ALL child cats? I don't want my client to have to go into the php each time he creates a new child cat. Is there any possible way to just limit all parent categories to 1 post? In other words, to exclude all child cats from appearing in the parent cat?

  8. Jacob Chappell
    Member
    Posted 2 years ago #

    Sure, you could do that. You'd just need first get all the child categories, organize them into an array of id's, then pass that to your query.

    You could use get_categories and use its child_of parameter (passing the parent category's id to there).

    After that, there are several ways to get just the id's into an array. You might try looping the categories array and creating a new array from just the ids like this:

    $categories = get_categories( $your_args_here );
    $exclude_these = array();
    foreach ( $categories as $category ) {
    	$exclude_these[] = $category->cat_ID;
    }
    
    // at this point, $exclude_these is a proper array  of
    // child categories that can be passed to your query
  9. amandach
    Member
    Posted 2 years ago #

    Don't I need to know the category ids this way? Is there any way to do it without having to specify the id's? Like I said, I don't want my client to have to go into the php each time he creates a new category.

  10. Jacob Chappell
    Member
    Posted 2 years ago #

    You only need to know the parent category's ID in order for that method to work (which should be one of wp_query's default options on the category view page). Try globalizing wp_query and then printing it and see what's in there:

    On category template:

    global $wp_query;
    echo '<pre>' . print_r( $wp_query, true ) . '</pre>';

    You can also try doing that with the $query_string global. If you can find the category slug you can get the ID from that through one of WordPress's functions.

  11. amandach
    Member
    Posted 2 years ago #

    Is there a plugin that can do this automatically? Because my client will have to do this again for a new parent category he adds.

  12. Jacob Chappell
    Member
    Posted 2 years ago #

    There probably are plugins, but that's what I was saying about gathering the category from wp_query.

    Whenever you go to a category detail page like this:
    yoursite.com/category/category-name

    WP_Query automatically knows some things about that page (that's how it displays the categories to begin with). You can use that slug that's passed in to get the category id of whatever category is currently being viewed. Because of that, the code will work dynamically for all categories.

    If you'd like, I can write up a working prototype for you. :)

  13. amandach
    Member
    Posted 2 years ago #

    Jacob that would be awesome if you can write something up for me. I'm not really getting it.

    You rock!

    Amanda

  14. Jacob Chappell
    Member
    Posted 2 years ago #

    Here you go :)
    I tested this on my test blog; it's fully functional code.

    http://pastebin.com/MfUbMwti

  15. amandach
    Member
    Posted 2 years ago #

    Great I'll get this on the site and let you know if it works!! Thanks so much!

  16. Jacob Chappell
    Member
    Posted 2 years ago #

    No problem; hope it works out for you!

    Remember, that code goes in the category.php template :)

  17. amandach
    Member
    Posted 2 years ago #

    So...it didn't work. Am I supposed to be modifying anything in it? I pasted it in category.php

  18. Jacob Chappell
    Member
    Posted 2 years ago #

    Well you don't copy/paste it verbatim. Your category.php template should already have a loop section setup that looks something like this:

    if ( have_posts() ) : while ( have_posts() ) : the_post();
    // stuff here
    endwhile;
    endif;

    You need to modify the query just before starting the loop (that's most of the code I gave you).

  19. Jacob Chappell
    Member
    Posted 2 years ago #

    In fact, why don't you post your category.php template to pastebin for me to take a look at (if you don't mind).

  20. amandach
    Member
    Posted 2 years ago #

    Sure thank you. I'm kind of new to wordpress and I'm nervous with messing around with its code -

    <?php
    /**
     * WordPress Category API
     *
     * @package WordPress
     */
    
    /**
     * Retrieves all category IDs.
     *
     * @since 2.0.0
     * @link http://codex.wordpress.org/Function_Reference/get_all_category_ids
     *
     * @return object List of all of the category IDs.
     */
    function get_all_category_ids() {
    	if ( ! $cat_ids = wp_cache_get( 'all_category_ids', 'category' ) ) {
    		$cat_ids = get_terms( 'category', 'fields=ids&get=all' );
    		wp_cache_add( 'all_category_ids', $cat_ids, 'category' );
    	}
    
    	return $cat_ids;
    }
    
    /**
     * Retrieve list of category objects.
     *
     * If you change the type to 'link' in the arguments, then the link categories
     * will be returned instead. Also all categories will be updated to be backwards
     * compatible with pre-2.3 plugins and themes.
     *
     * @since 2.1.0
     * @see get_terms() Type of arguments that can be changed.
     * @link http://codex.wordpress.org/Function_Reference/get_categories
     *
     * @param string|array $args Optional. Change the defaults retrieving categories.
     * @return array List of categories.
     */
    function &get_categories( $args = '' ) {
    	$defaults = array( 'type' => 'category' );
    	$args = wp_parse_args( $args, $defaults );
    
    	$taxonomy = apply_filters( 'get_categories_taxonomy', 'category', $args );
    	if ( 'link' == $args['type'] )
    		$taxonomy = 'link_category';
    	$categories = (array) get_terms( $taxonomy, $args );
    
    	foreach ( array_keys( $categories ) as $k )
    		_make_cat_compat( $categories[$k] );
    
    	return $categories;
    }
    
    /**
     * Retrieves category data given a category ID or category object.
     *
     * If you pass the $category parameter an object, which is assumed to be the
     * category row object retrieved the database. It will cache the category data.
     *
     * If you pass $category an integer of the category ID, then that category will
     * be retrieved from the database, if it isn't already cached, and pass it back.
     *
     * If you look at get_term(), then both types will be passed through several
     * filters and finally sanitized based on the $filter parameter value.
     *
     * The category will converted to maintain backwards compatibility.
     *
     * @since 1.5.1
     * @uses get_term() Used to get the category data from the taxonomy.
     *
     * @param int|object $category Category ID or Category row object
     * @param string $output Optional. Constant OBJECT, ARRAY_A, or ARRAY_N
     * @param string $filter Optional. Default is raw or no WordPress defined filter will applied.
     * @return mixed Category data in type defined by $output parameter.
     */
    function &get_category( $category, $output = OBJECT, $filter = 'raw' ) {
    	$category = get_term( $category, 'category', $output, $filter );
    	if ( is_wp_error( $category ) )
    		return $category;
    
    	_make_cat_compat( $category );
    
    	return $category;
    }
    
    /**
     * Retrieve category based on URL containing the category slug.
     *
     * Breaks the $category_path parameter up to get the category slug.
     *
     * Tries to find the child path and will return it. If it doesn't find a
     * match, then it will return the first category matching slug, if $full_match,
     * is set to false. If it does not, then it will return null.
     *
     * It is also possible that it will return a WP_Error object on failure. Check
     * for it when using this function.
     *
     * @since 2.1.0
     *
     * @param string $category_path URL containing category slugs.
     * @param bool $full_match Optional. Whether should match full path or not.
     * @param string $output Optional. Constant OBJECT, ARRAY_A, or ARRAY_N
     * @return null|object|array Null on failure. Type is based on $output value.
     */
    function get_category_by_path( $category_path, $full_match = true, $output = OBJECT ) {
    	$category_path = rawurlencode( urldecode( $category_path ) );
    	$category_path = str_replace( '%2F', '/', $category_path );
    	$category_path = str_replace( '%20', ' ', $category_path );
    	$category_paths = '/' . trim( $category_path, '/' );
    	$leaf_path  = sanitize_title( basename( $category_paths ) );
    	$category_paths = explode( '/', $category_paths );
    	$full_path = '';
    	foreach ( (array) $category_paths as $pathdir )
    		$full_path .= ( $pathdir != '' ? '/' : '' ) . sanitize_title( $pathdir );
    
    	$categories = get_terms( 'category', "get=all&slug=$leaf_path" );
    
    	if ( empty( $categories ) )
    		return null;
    
    	foreach ( $categories as $category ) {
    		$path = '/' . $leaf_path;
    		$curcategory = $category;
    		while ( ( $curcategory->parent != 0 ) && ( $curcategory->parent != $curcategory->term_id ) ) {
    			$curcategory = get_term( $curcategory->parent, 'category' );
    			if ( is_wp_error( $curcategory ) )
    				return $curcategory;
    			$path = '/' . $curcategory->slug . $path;
    		}
    
    		if ( $path == $full_path )
    			return get_category( $category->term_id, $output );
    	}
    
    	// If full matching is not required, return the first cat that matches the leaf.
    	if ( ! $full_match )
    		return get_category( $categories[0]->term_id, $output );
    
    	return null;
    }
    
    /**
     * Retrieve category object by category slug.
     *
     * @since 2.3.0
     *
     * @param string $slug The category slug.
     * @return object Category data object
     */
    function get_category_by_slug( $slug  ) {
    	$category = get_term_by( 'slug', $slug, 'category' );
    	if ( $category )
    		_make_cat_compat( $category );
    
    	return $category;
    }
    
    /**
     * Retrieve the ID of a category from its name.
     *
     * @since 1.0.0
     *
     * @param string $cat_name Optional. Default is 'General' and can be any category name.
     * @return int 0, if failure and ID of category on success.
     */
    function get_cat_ID( $cat_name='General' ) {
    	$cat = get_term_by( 'name', $cat_name, 'category' );
    	if ( $cat )
    		return $cat->term_id;
    	return 0;
    }
    
    /**
     * Retrieve the name of a category from its ID.
     *
     * @since 1.0.0
     *
     * @param int $cat_id Category ID
     * @return string Category name
     */
    function get_cat_name( $cat_id ) {
    	$cat_id = (int) $cat_id;
    	$category = &get_category( $cat_id );
    	return $category->name;
    }
    
    /**
     * Check if a category is an ancestor of another category.
     *
     * You can use either an id or the category object for both parameters. If you
     * use an integer the category will be retrieved.
     *
     * @since 2.1.0
     *
     * @param int|object $cat1 ID or object to check if this is the parent category.
     * @param int|object $cat2 The child category.
     * @return bool Whether $cat2 is child of $cat1
     */
    function cat_is_ancestor_of( $cat1, $cat2 ) {
    	if ( ! isset($cat1->term_id) )
    		$cat1 = &get_category( $cat1 );
    	if ( ! isset($cat2->parent) )
    		$cat2 = &get_category( $cat2 );
    
    	if ( empty($cat1->term_id) || empty($cat2->parent) )
    		return false;
    	if ( $cat2->parent == $cat1->term_id )
    		return true;
    
    	return cat_is_ancestor_of( $cat1, get_category( $cat2->parent ) );
    }
    
    /**
     * Sanitizes category data based on context.
     *
     * @since 2.3.0
     * @uses sanitize_term() See this function for what context are supported.
     *
     * @param object|array $category Category data
     * @param string $context Optional. Default is 'display'.
     * @return object|array Same type as $category with sanitized data for safe use.
     */
    function sanitize_category( $category, $context = 'display' ) {
    	return sanitize_term( $category, 'category', $context );
    }
    
    /**
     * Sanitizes data in single category key field.
     *
     * @since 2.3.0
     * @uses sanitize_term_field() See function for more details.
     *
     * @param string $field Category key to sanitize
     * @param mixed $value Category value to sanitize
     * @param int $cat_id Category ID
     * @param string $context What filter to use, 'raw', 'display', etc.
     * @return mixed Same type as $value after $value has been sanitized.
     */
    function sanitize_category_field( $field, $value, $cat_id, $context ) {
    	return sanitize_term_field( $field, $value, $cat_id, 'category', $context );
    }
    
    /* Tags */
    
    /**
     * Retrieves all post tags.
     *
     * @since 2.3.0
     * @see get_terms() For list of arguments to pass.
     * @uses apply_filters() Calls 'get_tags' hook on array of tags and with $args.
     *
     * @param string|array $args Tag arguments to use when retrieving tags.
     * @return array List of tags.
     */
    function &get_tags( $args = '' ) {
    	$tags = get_terms( 'post_tag', $args );
    
    	if ( empty( $tags ) ) {
    		$return = array();
    		return $return;
    	}
    
    	$tags = apply_filters( 'get_tags', $tags, $args );
    	return $tags;
    }
    
    /**
     * Retrieve post tag by tag ID or tag object.
     *
     * If you pass the $tag parameter an object, which is assumed to be the tag row
     * object retrieved the database. It will cache the tag data.
     *
     * If you pass $tag an integer of the tag ID, then that tag will
     * be retrieved from the database, if it isn't already cached, and pass it back.
     *
     * If you look at get_term(), then both types will be passed through several
     * filters and finally sanitized based on the $filter parameter value.
     *
     * @since 2.3.0
     *
     * @param int|object $tag
     * @param string $output Optional. Constant OBJECT, ARRAY_A, or ARRAY_N
     * @param string $filter Optional. Default is raw or no WordPress defined filter will applied.
     * @return object|array Return type based on $output value.
     */
    function &get_tag( $tag, $output = OBJECT, $filter = 'raw' ) {
    	return get_term( $tag, 'post_tag', $output, $filter );
    }
    
    /* Cache */
    
    /**
     * Update the categories cache.
     *
     * This function does not appear to be used anymore or does not appear to be
     * needed. It might be a legacy function left over from when there was a need
     * for updating the category cache.
     *
     * @since 1.5.0
     *
     * @return bool Always return True
     */
    function update_category_cache() {
    	return true;
    }
    
    /**
     * Remove the category cache data based on ID.
     *
     * @since 2.1.0
     * @uses clean_term_cache() Clears the cache for the category based on ID
     *
     * @param int $id Category ID
     */
    function clean_category_cache( $id ) {
    	clean_term_cache( $id, 'category' );
    }
    
    /**
     * Update category structure to old pre 2.3 from new taxonomy structure.
     *
     * This function was added for the taxonomy support to update the new category
     * structure with the old category one. This will maintain compatibility with
     * plugins and themes which depend on the old key or property names.
     *
     * The parameter should only be passed a variable and not create the array or
     * object inline to the parameter. The reason for this is that parameter is
     * passed by reference and PHP will fail unless it has the variable.
     *
     * There is no return value, because everything is updated on the variable you
     * pass to it. This is one of the features with using pass by reference in PHP.
     *
     * @since 2.3.0
     * @access private
     *
     * @param array|object $category Category Row object or array
     */
    function _make_cat_compat( &$category ) {
    	if ( is_object( $category ) ) {
    		$category->cat_ID = &$category->term_id;
    		$category->category_count = &$category->count;
    		$category->category_description = &$category->description;
    		$category->cat_name = &$category->name;
    		$category->category_nicename = &$category->slug;
    		$category->category_parent = &$category->parent;
    	} elseif ( is_array( $category ) && isset( $category['term_id'] ) ) {
    		$category['cat_ID'] = &$category['term_id'];
    		$category['category_count'] = &$category['count'];
    		$category['category_description'] = &$category['description'];
    		$category['cat_name'] = &$category['name'];
    		$category['category_nicename'] = &$category['slug'];
    		$category['category_parent'] = &$category['parent'];
    	}
    }
    
    ?>

    You're totally awesome -

    Amanda

  21. Jacob Chappell
    Member
    Posted 2 years ago #

    I can see now why you must have been confused before! That's not actually the right category.php file. The one I need is the template file that goes to whatever theme you're using.

    It should be located in the following folder:
    /wp-content/themes/YOUR_THEME_NAME/category.php

    If it's not there, then look for archive.php in the same folder. Lastly if that's not there, look for index.php.

    This is of course assuming that this isn't a child theme.

    Can you tell me what theme you're using?

  22. amandach
    Member
    Posted 2 years ago #

    My bad :)

    Here's archive.php. There's no category.php. I'm using default by anonymous.

    Here's the code

  23. Jacob Chappell
    Member
    Posted 2 years ago #

    No worries :)

    I've modified the code as necessary and re-posted it here:
    http://pastebin.com/D1JEPmjb

    I haven't tested it, but I don't see why it shouldn't work. I used the is_category() conditional to ensure that my changes only affect category pages (since this is in the global archive.php file).

    Let me know how it goes!

    Edit: Make a copy of your previous archive.php file before making any changes so that it's easy to restore if something goes wrong!

  24. amandach
    Member
    Posted 2 years ago #

    I pasted the code in archive.php but it didn't work :(

  25. Jacob Chappell
    Member
    Posted 2 years ago #

    Hmm, I went and created some categories and posts to test the code on and it seems to work for me. The only thing I can assume is that you either have a plugin that's altering the category query for some reason or we're not on the same page about what the code actually does.

    In WordPress when you visit a category index page (usually something like yoursite.com/category/category-name-here you will see all posts that are filed under that category and all child categories of it. The code I gave you limits that query to only show posts from the parent category (it excludes posts from all child categories of whatever category is currently being viewed).

    I know you had mentioned the Fold Category List plugin in your first reply, so I went and downloaded it to see what it was all about. Are you trying to edit the output of the plugin's category list? because if so there are tons of options in the Settings > FoCal menu in your WordPress admin.

  26. amandach
    Member
    Posted 2 years ago #

    Yes, that's what I'm trying to do. I want the posts in the parent category only to be shown in the parent category, and the posts from the child cats to be shown in the child cats only, not parent cat.

    I'm using this Fold Category List. It has different features than FoCal, which didn't work for me.

    It could be that the php in the fold category list is overriding what you wrote. Any other suggestions then? Does the php you gave me work with FoCal? I can install that again and see if I can work around it.

  27. Jacob Chappell
    Member
    Posted 2 years ago #

    As far as I can tell, both of those plugins have nothing to do with what posts are displayed in which categories. All they seem to do is change which categories get shown in your sidebar (or wherever you list categories at). You have to actually click on one of the listed categories to view what posts are in it (on your category/archive page).

    This being the case, I don't really see how either of those plugins would interfere with the code I gave you.

    If you did want to try FoCaL again, you first need to make sure your theme supports widgets because that's how FoCaL works -- you add a widget to your sidebar that lists categories but limits them to your specifications.

    I'm not really sure I have anything else I can tell you. Without actually working on your site myself, it's hard to debug and come up with solutions.

    You could try posting some screenshots of different page outputs you're getting or things you're trying.

  28. amandach
    Member
    Posted 2 years ago #

    I tried playing around with different plugins but nothing helped. Do you think if I create a separate category page for parent categories that would help? Can I use your code on an exclusive page just for parent categories and then call the other category page for the child cats? If yes, how would I go about it?

    You're a lifesaver Jacob, thanks for giving me the time!!

    Amanda

  29. Jacob Chappell
    Member
    Posted 2 years ago #

    Well the thing is the WordPress template hierarchy doesn't really work that way. You can create a category template for a specific category (using its slug or id), but there's no direct way to specify a template for just parent categories and a different one for child categories. That's generally not a problem though, because one can create a generic template and use conditional statements and custom queries to achieve the desired result.

    You can view a diagram of the template hierarchy here.

    You can see in that image that category pages go in this order:
    category-$slug.php > category-$id.php > category.php > archive.php

    In your case, you don't have any specific category templates and you don't have a generic category template, so your theme is falling back to the archive.php (which should be fine because we used conditionals).

    That's the thing that has me puzzled is I don't understand why your archive page isn't filtering your posts with the new code you added.

    One thing you can try is to create a new file called category.php so that it will be used explicitly for categories. I've attempted to modify your archive.php code to work for this new category.php page:

    http://pastebin.com/N3u0rQk2

    One line in your archive.php has me quite puzzled as well. Would you mind posting your header.php, footer.php, and functions.php as well?

    It's my pleasure to try and help out!

  30. amandach
    Member
    Posted 2 years ago #

    Really odd - I created a new page called category.php and it's still not working. All posts are showing up. Am I supposed to be changing anything else?

    Here is my header.php, footer.php and functions.php.

    Thank you!

Topic Closed

This topic has been closed to new replies.

About this Topic