How do I query a specifc child category on a page? - parent-child

I am trying to query a list of child categories that are specific to a page. In other words, if I go to the page with the slug 'us-mid-western-tour' it queries the children categories of parent cat with ID 49 and if I go to 'us-western-tour' it gets ID 21 and so on.
Here is my code so far but it is not working. Can anybody steer me in the right direction?
$taxonomy = 'tournament_category';
$orderby = 'name';
$hierarchical = 1;
$child = if ( is_page('us-mid-western-tour')) {
echo '49';
} elseif ( is_page('us-western-tour')) {
echo '21';
}
;
$args = array(
'taxonomy' => $taxonomy,
'orderby' => $orderby,
'hierarchical' => $hierarchical,
'hide_empty' => 0,
'child_of' => $child,
Thanks D

use this
if ( is_page('us-mid-western-tour')) {
$child = '49';
} elseif ( is_page('us-western-tour')) {
$child = '21';
}
I hope it will help

Related

Wordpress seo silo category/term-tree for sidebar

I created a sidebar for the dynamic WordPress category pages.
Example Url: https://example.com/category/firstcategory/secondcategory/othercategories/
SEO Silo:
Info about SEO Silos: What is a content silo and how does it benefit for SEO?
An imaginary company offers books, films and toys. And so the following categories are usually formed:
Company category:
* company
** books
** movies
** games
They have subcategories.
* company
** books
*** drama
*** comedy
** movies
*** drama
*** comedy
*** romance
** games
*** actions
*** for kids
*** click and point
The subcategories in turn have entries.
If I now come to the books category, only everything about books may appear in the category tree and not movies and games as well. Ideally not even the upper category, like that:
* company
** books
*** drama
---- drama Book1
---- drama Book2
If I'm in the drama category for books, I dont want to see the others like comedy in the books category too.
If I'm in the Company category, its okay to see the first subcategories like:
* company
** books
** movies
** games
If I'm in the books category:
* company
** books
*** drama
*** comedy
Problem:
The code isn't optimized yet, because I'm just trying out a lot.
Active Category level 2 already works (apart from the indentation).
When calling up the second category, sometimes not all (existing) sub-categories appear.
Probably the smallest problem is that the categories are not indented as a list.
// Manual: https://stackoverflow.com/questions/9225920/how-to-check-which-level-category-it-is-for-wordpress
function get_the_level($id, $type = 'category') {
return count(get_ancestors($id, $type));
}
function children_sidebar_shortcode($atts) {
global $post;
if (!is_category()) {
return false;
}
$returnval = "";
$category = get_queried_object();
$category_id = $category->term_id;
$n = 0;
$item_cat_level = 0;
// Active Category is level 2 and more
if (get_the_level($category_id) >= 2) {
$returnval .= "<h2>Active Category is level 2 and more</h2>";
$args = array(
'type' => 'post',
'child_of' => 0,
'parent' => '',
'orderby' => 'term_group', //'name',
'order' => 'ASC',
'hide_empty' => 0,
'hierarchical' => 1,
'exclude' => '',
'include' => '',
'number' => '',
'taxonomy' => 'category',
'pad_counts' => false
);
} else {
$returnval .= "<h2>Active Category is level 1 or less</h2>";
$args = array(
'type' => 'post',
'child_of' => $category_id,
'parent' => '', // set here same category as you want to fetch only their 1st level category on in depth child
'orderby' => 'term_group', //'name',
'order' => 'ASC',
'hide_empty' => 0,
'hierarchical' => 1,
'exclude' => '',
'include' => '',
'number' => '',
'taxonomy' => 'category',
'pad_counts' => false
);
}
$categories = get_categories($args);
if (count($categories) > 0) {
// show the category description
//$returnval .= category_description();
$returnval .= "<ul>";
foreach ($categories as $category) {
$item_cat_level = get_the_level($category->term_id);
// Active Category is level 2 and more
if (get_the_level($category_id) >= 2) {
if (
// Category is part of the parent Categories/Terms
cat_is_ancestor_of($category->term_id, $category_id)
// SubLevel Category 2
|| $item_cat_level >= 2
// Active Category (same)
|| $category->term_id === $category_id
) {
$category_link = sprintf(
'%3$s',
esc_url(get_category_link($category->term_id)),
esc_attr($category->name),
esc_html($category->name)
);
$returnval .= sprintf("<li class='cat-item cat-item-%d %s'>%s", $category_id, ($category->term_id === $category_id) ? 'current-cat-ancestor' : '', $category_link);
}
} else {
if (
// Category is part of the parent Categories/Terms
//cat_is_ancestor_of($category->term_id, $category_id)
// SubLevel Category 2
//||
$item_cat_level <= 1
// Active Category (same)
//|| $category->term_id === $category_id
) {
$category_link = sprintf(
'%3$s',
esc_url(get_category_link($category->term_id)),
esc_attr($category->name),
esc_html($category->name)
);
$returnval .= sprintf("<li class='cat-item cat-item-%d %s'>%s", $category_id, ($category->term_id === $category_id) ? 'current-cat-ancestor' : '', $category_link);
}
}
}
$returnval .= "</ul>";
}
// Attributes
$atts = shortcode_atts(
array(
'name' => '',
),
$atts,
''
);
return $returnval;
}
add_shortcode('children_sidebar', 'children_sidebar_shortcode');
So looking at the edited question, I think what you are really looking for is, a category tree having only the (immediate) children or siblings of the current category (i.e. the queried object/term on a category archive page), right?
If so, then this should work for you:
function children_sidebar_shortcode( $atts ) {
// Do nothing if we're not on a category archive.
if ( ! is_category() ) {
return '';
}
// Parse the shortcode's parameters.
$atts = shortcode_atts( array(
'show_parent' => 1,
), $atts );
// Get the queried category object and ID.
$current_cat = get_queried_object();
$current_cat_id = $current_cat->term_id;
// Get the category's immediate children, if any.
$parent_cat_id = $current_cat_id;
$categories = get_categories( array(
'parent' => $parent_cat_id,
'hide_empty' => 1,
) );
// If none, get its siblings.
// .. which means it's the last level.
if ( empty( $categories ) ) {
$parent_cat_id = $current_cat->parent;
$categories = get_categories( array(
'parent' => $parent_cat_id,
'hide_empty' => 1,
) );
}
$heading = '';
$list = '<ul class="cat-list">';
foreach ( $categories as $term ) {
$class = 'cat-item';
// If it's the current category, show the name only.
if ( $current_cat_id === $term->term_id ) {
$class .= ' current-cat';
$cat_name = '<span>' . esc_html( $term->name ) . '</span>';
// If it's not the current category, add a link to view the category
// archive.
} else {
$cat_name = '<a href="' . esc_url( get_category_link( $term ) ) . '">' .
esc_html( $term->name ) . '</a>';
}
$list .= "<li class='$class'>$cat_name</li>";
}
$list .= '</ul>';
if ( $parent_cat_id && $atts['show_parent'] ) {
$term = get_category( $parent_cat_id );
$heading = '<h3>' . esc_html( $term->name ) . '</h3>';
}
return "$heading $list";
}
Note regarding the shortcode parameters: I added show_parent, which if true or 1, then the immediate parent category will always be added to the output. So for example, on the Books category page, the shortcode would output something like this: (the "Books" is not a link)
Books
● Comedy
● Drama
And BTW, using a custom function to manually generate the categories list (i.e. the <li> tags) will give you full control over the HTML markup, but just so that you know, you could also use wp_list_categories() like so:
Just replace the entire foreach above with this:
$list .= wp_list_categories( array(
'current_category' => $current_cat_id,
'parent' => $parent_cat_id,
'hide_empty' => 1,
'title_li' => '',
'echo' => 0,
) );
Last but not least, you can style the current category/<li> using the current-cat class. :)
The answer is only a temporary solution:
I tried indenting with the query for a level change. Until then set an optical (but not semantic) indentation by a margin-left-0 to 2. With classes ml-%d (0,1,2).
// Manual: https://stackoverflow.com/questions/9225920/how-to-check-which-level-category-it-is-for-wordpress
function get_the_level($id, $type = 'category') {
return count(get_ancestors($id, $type));
}
function children_sidebar_shortcode($atts) {
global $post;
if (!is_category()) {
return false;
}
$returnval = "";
$category = get_queried_object();
$category_id = $category->term_id;
$item_cat_level_last = 0;
$item_cat_level = 0;
// Active Category is level 2 and more
if (get_the_level($category_id) >= 2) {
//$returnval .= "<h2>Active Category is level 2 and more</h2>";
$args = array(
'type' => 'post',
'child_of' => 0,
'parent' => '',
'orderby' => 'term_group', //'name',
'order' => 'ASC',
'hide_empty' => 1,
'hierarchical' => 1,
'exclude' => '',
'include' => '',
'number' => '',
'taxonomy' => 'category',
'pad_counts' => false
);
} else {
//$returnval .= "<h2>Active Category is level 1 or less</h2>";
$args = array(
'type' => 'post',
'child_of' => $category_id,
'parent' => '', // set here same category as you want to fetch only their 1st level category on in depth child
'orderby' => 'term_group', //'name',
'order' => 'ASC',
'hide_empty' => 1,
'hierarchical' => 1,
'exclude' => '',
'include' => '',
'number' => '',
'taxonomy' => 'category',
'pad_counts' => false
);
}
$categories = get_categories($args);
if (count($categories) > 0) {
// show the category description
//$returnval .= category_description();
$returnval .= "<ul>";
foreach ($categories as $category) {
$item_cat_level = get_the_level($category->term_id);
// Active Category is level 2 and more
if (get_the_level($category_id) >= 2) {
if (
// Category is part of the parent Categories/Terms
cat_is_ancestor_of($category->term_id, $category_id)
// SubLevel Category 2
|| $item_cat_level >= 2
// Active Category (same)
|| $category->term_id === $category_id
) {
if ($item_cat_level >= 2) {
$category_link = sprintf(
'%3$s',
esc_url(get_category_link($category->term_id)),
esc_attr($category->name),
esc_html($category->name)
);
}else{
$category_link = esc_html($category->name);
}
$returnval .= sprintf("<li class='cat-item ml-%d cat-item-%d %s'>%s", $item_cat_level, $category_id, ($category->term_id === $category_id) ? 'current-cat-ancestor' : '', $category_link);
}
} else {
if (
// Category is part of the parent Categories/Terms
//cat_is_ancestor_of($category->term_id, $category_id)
// SubLevel Category 2
//||
$item_cat_level <= 1
// Active Category (same)
//|| $category->term_id === $category_id
) {
/*$category_link = sprintf(
'%3$s',
esc_url(get_category_link($category->term_id)),
esc_attr($category->name),
esc_html($category->name)
);*/
$category_link = esc_attr($category->name);
$returnval .= sprintf("<li class='cat-item ml-%d cat-item-%d %s'>%s", $item_cat_level, $category_id, ($category->term_id === $category_id) ? 'current-cat-ancestor' : '', $category_link);
}
}
/*if ($item_cat_level > $item_cat_level_last){
$item_cat_level_last = $item_cat_level;
$returnval .= "<ul class='children'></ul>";
}*/
$returnval .= "</li>";
}
$returnval .= "</ul>";
}
// Attributes
$atts = shortcode_atts(
array(
'name' => '',
),
$atts,
''
);
return $returnval;
}
add_shortcode('children_sidebar', 'children_sidebar_shortcode');
I didn't link the first two category levels where the output doesn't work yet, until the code optimization.
With a direct call, a 301 (permanent) redirect, which is removed again when the code is optimized.
<IfModule mod_rewrite.c>
RewriteEngine On
RedirectMatch 301 ^/category/firstcategory/secondcategory/?$ https://example.com/firstcategory/secondcategory-page/
</IfModule>

WordPress listing all/selected pages in A-Z index

I want to list all pages as well as selected pages in A-Z listing in WordPress. I know there are a number of plugins available, but I want this without a plugin.
Update
sorry if question is not clear, i want A-Z listing like attached image
i have solved this issue,
just need to put if condition, here is the code
$arr[0] = array(2=>2983);
$arr[1] = array(2=>2981);
$arr[2] = array('A'=>20);
$arr[3] = array('A'=>25);
print "<pre>";
print_r($arr);
$newArry = array();
foreach ($arr as $a) {
foreach ($a as $key => $value) {
if (array_key_exists($key, $newArry)) {
//$newArry[$key] = array($value);
array_push($newArry[$key], $value);
} else {
$newArry[$key] = array($value);
}
echo "<br/> Key ".$key ." => Value ".$value;
//print_r($b);
}
}
print_r($newArry);
You can use a WP_Query, as page is simply a post type.
$args = array(
'post_type' => 'page',
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
);
$query = new WP_Query( $args );
$pages = $query->posts;
See WP_Query documentation.

Show all terms excluding the current page

The following lists all of the terms, can I get help revising it so that it shows all terms except the the active/current page? Thank you.
$terms = get_terms( 'topics', array(
'orderby' => 'name',
'order' => 'ASC',
));
if ( ! empty( $terms ) ){
foreach ( $terms as $term ) {
$term_thumb = get_field('image', $term);
echo '<li><img src="' .$term_thumb['url']. '"><span class="model">'.$term->name .'</span></li>';
}
}
You can do something like this:
// create an empty array holder
$current_tax_ids = array();
// get the post terms
$current_tax = get_the_terms( $post->ID, 'topics' );
// creating loop to insert ids
foreach( $current_tax as $tax ) {
$current_tax_ids[] = $tax->term_id;
}
$args = array(
'taxonomy' => 'topics',
'hide_empty' => 0,
'exclude' => $current_tax_ids // exclude the terms
);
// get all the terms
$all_terms = get_terms($args);
// now do whatever you want
so if you follow my comments it should be clear, but basically you want to get the current post terms and store the id in an array, then simply exclude the ids when you do get_terms .

Wordpress - Get the taxonomy of a post hierarchically

I would like to get all the taxonomy of one post (in a loop), hierarchically. Example I have those taxonomies, and the ID of the tax in bracket.
Tax1(1)
-Tax2(3)
--Tax3(2)
I would like to gather them, in an array maybe, in this order. Right now I manage to get an array of those 3, but the order is wrong. I can't order it by id, since the ID are not ordered at first. I can't also order it by name and slug. (Names of my current taxonomies are not Tax1, Tax2...)
The code I have at the moment is
$args = array('orderby' => 'term_order', 'order' => 'ASC', 'fields' => 'all');
$productcategories = wp_get_object_terms($post->ID, 'guide_type', $args);
Use "Wordpress" Walker class to create a hierarchy of the taxonomy
<?php
class Walker_Quickstart extends Walker {
// Tell Walker where to inherit it's parent and id values
var $db_fields = array(
'parent' => 'parent',
'id' => 'term_id'
);
/**
* At the start of each element, output a <p> tag structure.
*/
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
$output .= sprintf( "\n<p>%s %s (%s)</p>\n",
str_repeat('&dash;', $depth),
$item->name,
$item->term_id
);
}
}?>
This class will create a hierarchy of elements. Use this class with your returned elements like this :
$args = array('orderby' => 'term_order', 'order' => 'ASC', 'fields' => 'all');
$productcategories = wp_get_object_terms($post->ID, 'guide_type', $args);
$walk = new Walker_Quickstart();
echo $walk->walk($productcategories, 0);
Was about to get something with this function that I made, But Vikash Kumar gave me a better answer, thanks !
function get_term_top_most_parent($post_id, $taxonomy){
$return = array();
$registeredcat = 0;
$newparent = '';
$catcount = 0;
$firstlevels = wp_get_object_terms( $post_id, $taxonomy); //post id, taxo, args
foreach ($firstlevels as $key => $value){
if($value->parent == 0 ){
//$firstlevel = $value->term_id; //23
$newparent = $value->term_id;
array_push($return, $value);
$registeredcat += 1;
}
$catcount += 1;
}
return $return;
}

Get no of posts inside with a term for a custom taxonomy

How can i get the no of posts inside a term of a custom taxonomy ? (including the posts that are attached to a child term).
For example i have:
term (2 posts)
-child term (2 posts)
--child child term (1 post)
Right now i'm, doing it like this:
$categories = get_terms($taxonomy,$args);
foreach ($categories as $categ) {
print $categ->name.' / '.$categ->count;
}
But for "term" i get only 2 posts when i really need to show 5( 2 from "term" and 3 from it's children).
Thanks
There is an easier way to do this: do a standard WP_Query with taxonomy parameters:
$args = array(
'post_type' => 'post',
'tax_query' => array(
array(
'taxonomy' => 'your_custom_taxonomy',
'field' => 'slug',
'terms' => 'your-parent-term-name',
),
),
);
$query = new WP_Query( $args );
// Get the count
$count = $query->post_count;
If you don't know the name(s) of terms within a taxonomy, you can do a query and pass their IDs as an array to WP_Query. See this post on WPSE for more info.
This is something I run into few times, and I changed the code from PatchRanger on bountify to make it work with taxonomies (so please note this solution is based on his work):
function wp_get_term_postcount($term) {
$count = (int) $term->count;
$tax_terms = get_terms($term->taxonomy, array('child_of' => $term->term_id));
foreach ($tax_terms as $tax_term) {
$count += wp_get_term_postcount_recursive($tax_term->term_id);
}
return $count;
}
function wp_get_term_postcount_recursive($term_id, $excludes = array()) {
$count = 0;
foreach ($tax_terms as $tax_term) {
$tax_term_terms = get_terms($tax_term->name, array(
'child_of' => $tax_term->term_id,
'exclude' => $excludes,
));
$count += $tax_term->count;
$excludes[] = $tax_term->term_id;
$count += wp_get_term_postcount_recursive($tax_term->term_id, $excludes);
}
return $count;
}
The recursive function is there to prevent double counting of childs. You can add those two functions inside functions.php.
Then update your code to use it:
$categories = get_terms($taxonomy, $args);
foreach($categories as $categ) {
print $categ->name.' / 'wp_get_term_postcount($categ);
}

Resources