I have a category "Decouverte" witch has three subcategories : "actualité", "vidéo" and "coup de coeur".
When I sort the posts according to their subcategories, everything works except for the category "video"; the category_slug displays "decouverte".
On my dashboard, I see this :
The subcategory "Video" is displayed last, maybe it's why it doesn't work ?
My code :
$categories = get_the_category();
$category_slug = $categories[0]->slug;
echo $category_slug;
if ( $category_slug == 'actualite' ) { ?>
<div class="picto_home icone_actualite"></div><?php
}
elseif ( $category_slug == 'video' ) { ?>
<div class="picto_home icone_video"></div><?php
}
elseif ( $category_slug == 'coupdecoeur' ) { ?>
<div class="picto_home icone_coupdecoeur"></div><?php
}
else { echo "Doesn't work"; } ?>
And the website : http://www.overso.me/ It's on the right block
Problem source
It's because you have got two categories applied to all posts.
Categories in each post are sotrted alphabetically.
In your case you take $category_slug = $categories[0]->slug;, which means:
Take first category slug name from categories array
For each post it is:
$categories[0] = Decouverte, $categories[1] = Video because D < V
$categories[0] = Actualite, $categories[1] = Decouverte because A < D
$categories[0] = Coup de coeur, $categories[1] = Decouverte because C < D
How to make it work as you want
Ok so here is my approach for your problem.
Before checking for $categories[0]->slug, lets check is $categories[0] object a PARENT category. You can do this by checking:
$categories = get_the_category();
// Remove parent category object from array if it's on first place
if($categories[0]->parent == 0){
unset($categories[0]);
$categories = array_values($categories);
}
As you see if $categories[0] is a parent category (if($categories[0]->parent == 0)), then remove this result from array $categories - unset($categories[0]).
Now you can just reset indexing of this array to starting from 0, by calling $categories = array_values($categories).
From now, you can easly call $categories[0]->slug, because there is no parent category on first place for sure.
Full code:
$categories = get_the_category();
// Remove parent category object from array if it's on first place
if($categories[0]->parent == 0){
unset($categories[0]);
$categories = array_values($categories);
}
$category_slug = $categories[0]->slug;
if ( $category_slug == 'child-1' ) {
echo "1111";
}
elseif ( $category_slug == 'child-2' ) {
echo "2222";
}
elseif ( $category_slug == 'child-3' ) {
echo "3333";
}
else { echo "Doesn't work"; }
Of course change if statements logic to your data.
More general solution for future reference
Ok, here is some general solution I wrote.
If you need to get only subcategories for any post, for any number of categories applied to the post, and no matter on which place parent category will be in the categories array, you should try this.
First, add this function to your functions.php file (or to your plugin file).
function du_get_post_subcategories( $post_id ){
$categories = get_the_category( $post_id );
$i = 0;
foreach ($categories as $category) {
if($category->parent == 0){
unset($categories[$i]);
}
$i++;
}
$categories = array_values($categories);
return $categories;
}
And then inside your loop you can call
$subcategories = du_get_post_subcategories( $post->ID );
If you have post ID, you can call this outside the loop as well
$subcategories = du_get_post_subcategories( $your_post_id );
This function will return all subcategories in the same format as get_the_category() function.
If you provide array with only one, parent category. Function will return an empty array.
Related
I'm trying to build a query to a custom record type that would eventually output a category, and then all posts from that category. However, there is a point with categories with hierarchy. For such categories, I would like to display the parent category once, and not every time. So, I have this code:
<?php
$query = new WP_Query([
'post_type' => 'afdigit',
'posts_per_page' => -1,
'orderby' => 'none',
]);
if ($query->have_posts()) { ?>
<div class="cat">
<?php $q = array();
while ($query->have_posts()) {
$query->the_post();
$a = '' . get_the_title() . '';
$top_term = get_top_term('afd-cats');
$b = '' . $top_term->name . '';
$categories = get_the_terms($post_id, 'afd-cats');
foreach ($categories as $key => $category) {
$c = '' . $category->name . '';
}
if ($top_term->term_id == $category->term_id) {
$b;
} else {
$b = '<div class="top term_">' . $b . '</div>';
$b .= '<div class="child">' . $c . '</div>';
}
$q[$b][] = $a;
}
wp_reset_postdata();
foreach ($q as $key => $values) {
echo '<div class="term">';
echo $key;
echo '<ul class="posts">';
foreach ($values as $value) {
echo '<li class="post">' . $value . '</li>';
}
echo '</ul></div>';
} ?>
</div>
<?php }
wp_reset_postdata(); ?>
In function get_top_term(), I get the parent category if it exists.
function get_top_term($taxonomy, $post_id = 0)
{
isset($post_id->ID) && $post_id = $post_id->ID;
!$post_id && $post_id = get_the_ID();
$terms = get_the_terms($post_id, $taxonomy);
if (!$terms || is_wp_error($terms)) {
return $terms;
}
$term = array_shift($terms);
$parent_id = $term->parent;
while ($parent_id) {
$term = get_term_by('id', $parent_id, $term->taxonomy);
$parent_id = $term->parent;
}
return $term;
}
Here I get almost what I need, namely:
Category 1
Post
Post
Post
Category 2
Post
Post
Post
Parent category 1
Child category 1
Post
Post
Post
Parent category 1
Child category 2
Post
Post
Post
Category 3
Post
Post
Post
However, I would like to exclude repetitions of parent category so that it turns out like this:
Category 1
Post
Post
Post
Category 2
Post
Post
Post
Parent category 1
Child category 1
Post
Post
Post
Child category 2
Post
Post
Post
Category 3
Post
Post
Post
Unfortunately, I have too little knowledge of php. I hope for your help both in solving the first question, and perhaps with advice on how to improve this code. Thanks)
I have created a template named category-south-africa.php. I would like all child, grandchild, great grandchild categories to automatically use this template. For example, all these categories must use the category-south-africa.php template:
/category/south-africa/
/category/south-africa/stellenbosch/
/category/south-africa/stellenbosch/wine-farm/
/category/south-africa/stellenbosch/wine-farm/wine-varietal/
Does anyone perhaps have a php function solution?
You can create you own template for this. You can check the category_template filter and do something like this.
add_filter('category_template', 'add_top_term_template');
function add_top_term_template($template) {
$term = get_queried_object();
$parent = $term->parent;
if($parent === 0) {
return $template;
}
$topLevel = null;
while($parent !== 0) {
$topLevel = get_term($parent);
$parent = $topLevel->parent;
}
$templates = ["term-top-level-{$topLevel->slug}.php"];
return locate_template($templates);
}
You can find more info about the filter here: https://codex.wordpress.org/Plugin_API/Filter_Reference/category_template
get_ancestors() that returns an array containing the parents of any given category.
use like get_ancestors( child_category_id, 'category' );
Check the value is in the array or not. if yes then define template name.
You can use this function to check if the current category is a child category and set the template to the same you have for the parent category. Put this in the functions.php of your theme.
function childcategory_template( $template ) {
$cat = get_queried_object();
if( 0 < $cat->category_parent )
$template = locate_template( 'category-south-africa.php');
return $template;
}
add_filter( 'category_template', 'childcategory_template' );
Edit after comment: You can also check the name (slug) and set the $template variable taking the name (slug) of the parent into account.
function childcategory_template( $template ) {
$cat = get_queried_object();
if( 0 < $cat->category_parent )
$parent_id = $cat->category_parent;
if ( get_category( $parent_id )->slug == "south-africa" ) {
$template = locate_template( 'category-south-africa.php');
} else if ( get_category( $parent_id )->slug == "north-africa" ) {
$template = locate_template( 'category-north-africa.php');
}
return $template;
}
add_filter( 'category_template', 'childcategory_template' );
I have a category, I want to show in my sidebar with the total number of posts(how many posts this category has).
You can try this plugin https://wordpress.org/plugins/category-posts/
Or if you like code yourself. Here it is:
You can use the method get_posts for getting result which accepts single array parameter or string parameter as given below.
<?php $posts = get_posts('post_type=post&category=4');
$count = count($posts);
echo $count;
?>
Explanation for above code:
It fetches posts result from the table wp_posts whose post_type is post and belongs to the category id 4. Then we used php function count for getting total records.
If you need only published posts additionally add post_status=publish.
function wpb_postsbycategory() {
// the query
$the_query = new WP_Query( array( 'category_name' => 'announcements', 'posts_per_page' => 10 ) );
$posts = get_posts('post_type=post&category_name=announcements');
$count = count($posts);
// The Loop
if ( $the_query->have_posts() ) {
$string .= "<p>Total:<strong>{$count}</strong></p>";
$string .= '<ul class="postsbycategory widget_recent_entries">';
while ( $the_query->have_posts() ) {
$the_query->the_post();
if ( has_post_thumbnail() ) {
$string .= '<li>';
$string .= '' . get_the_post_thumbnail($post_id, array( 50, 50) ) . get_the_title() .'</li>';
} else {
// if no featured image is found
$string .= '<li>' . get_the_title() .'</li>';
}
}
} else {
// no posts found
}
$string .= '</ul>';
return $string;
/* Restore original Post Data */
wp_reset_postdata();
}
// Add a shortcode
add_shortcode('categoryposts', 'wpb_postsbycategory');
// Enable shortcodes in text widgets
add_filter('widget_text', 'do_shortcode');
By using the above function you can produce the resultant output. (for reference Show recent posts by category
Simply visit Appearance » Widgets menu and add a text widget to your sidebar. Next add [categoryposts] shortcode in the text widget and save it.
To count total number of post of a specific category this method can be used.
<?php
function count_cat_post($category) {
//you can pass name of the category such as 'js'
if(is_string($category)) {
$catID = get_cat_ID($category);
}
//you can also pass id of the category
elseif(is_numeric($category)) {
$catID = $category;
} else {
return 0;
}
$cat = get_category($catID);
return $cat->count;
}
//finally call the function
count_cat_post('js');//or pass the category id as argument
?>
Either this is harder than it needs to be or I am just not understanding WordPress/PHP very well :( All I want to do is show the child/sub categories of a specific parent category...but only if the post is in those subcategories. Specific example:
I am building a wine reviews website and these are the categories:
BrandSubcategory 1Subcategory 2etc.
RegionSubcategory 1Subcategory 2etc.
GrapeSubcategory 1Subcategory 2etc.
The parent categories will never change, and every post will have at least 1 subcategory selected under each parent, so in the LOOP I can just list the parents by name. But I am needing to dynamically output the subcategories, something like this:
Brand: <?php list_post_subcategories('brand'); ?>
Region: <?php list_post_subcategories('region'); ?>
Grape: <?php list_post_subcategories('grape'); ?>
Is there any easy way like this? It seems like this should be a basic function in Wordpress? I've looked at the functions 'get_categories' and 'in_category' but they don't seem to be able to do this.
<?php $post_child_cat = array();
foreach((get_the_category()) as $cats) {
$args = array( 'child_of' => $cats->cat_ID );
$categories = get_categories( $args );
if( $categories ) foreach( $categories as $category ) {
echo $category->cat_name; }
} ?>
try this
I posted to Wordpress Answers to get more help and #Milo gave a great code solution:
// get top level terms
$parents = get_terms( 'category', array( 'parent' => 0 ) );
// get post categories
$categories = get_the_terms( $post->ID, 'category' );
// output top level cats and their children
foreach( $parents as $parent ):
// output parent name and link
echo '' . $parent->name . ': ';
// initialize array to hold child links
$links = array();
foreach( $categories as $category ):
if( $parent->term_id == $category->parent ):
// put link in array
$links[] = '' . $category->name . '';
endif;
endforeach;
// join and output links with separator
echo join( ', ', $links );
endforeach;
You can use array_map so you can return only the categories that you want. For example:
array_map( function( $cat ) {
if ( $cat->parent != 0 ) {
return $cat;
}
},
get_the_category()
);
wordpress have function the_category(''); for show all category assigned to te current post , but i need to get current category only child and not show parent .
for example my post have category category parent --> category child and the_category; print :your post cat is : ( category parent , category child )
i neeed parint , your post cat is : (category child) and not show parent .
Use get_the_category function , witch will return all categories asigned to a post ( this means all parents and childs allso ) so you can loop thru them and see witch one is parent and witch one is child and print the one you're trying to get . I suggest you build a function in you're theme functions file.
Update
For example let's say you whant to display the child category name in you're single.php theme file so you would do this:
<?php $child_category = post_child_category(get_the_ID()); ?>
<?php if ( $child_category ) echo $child_category->cat_name; ?>
In order for that to work you need to define post_child_category function in you're theme functions file ( if you look in you're theme directory you'll see a functions.php file , if not then you can create it now ) , so you would add the following :
if ( ! function_exists( 'post_child_category' ) )
{
function post_child_category( $id = null )
{
if ( $id = null )
return false;
$categories = get_the_category( $id );
if ( count($categories) > 0 )
{
return $categories[count($categories)-1];
} else {
return false;
}
}
}
Update
If you whant to display the category link you would do this :
<?php $child_category = post_child_category(get_the_ID()); ?>
<?php if ( $child_category ) : ?>
<a href="<?php echo get_category_link($child_category->cat_ID); ?>" title="<?php echo $child_category->cat_name;?>">
<?php echo $child_category->cat_name;?>
</a>
<?php endif;?>
<ul>
<?php
$blogCategoryID = "5"; // current category ID
$childCatID = $wpdb->get_col("SELECT term_id FROM $wpdb->term_taxonomy WHERE parent=$blogCategoryID");
if ($childCatID){
foreach ($childCatID as $kid)
{
$childCatName = $wpdb->get_row("SELECT name, term_id FROM $wpdb->terms WHERE term_id=$kid");
?>
<li><?php echo $childCatName->name; ?></li>
<?php
}
}
?>
</ul>
take a look at :
http://codex.wordpress.org/Function_Reference/wp_list_categories
this worked for me
$catID=$wp_query->query_vars['cat'];
$args = array('parent' => $catID);
$categories = get_categories( $args );
foreach($categories as $category) {
echo '<li><a href="' . get_category_link( $category->term_id ) . '" ' . '>' . $category->name.'</a> </li> ';
}