I got this code in my function.php which shows available sizes on all the products in the category view of woocommerce.
The problem is that it takes a lot of resources and makes the site slow.
My question is, if I should save the data for each product in a transient cache to speed up the site? But it would require a lot of transients, as each product should have a transitent – Is it a good way to do it like I think or is it bad pratice to have so many transients?
My thought was to make each product have a transient key like:
$key = 'my_transient_key' . $product->get_id();
The function code as it is now:
add_action( 'woocommerce_after_shop_loop_item_title', 'display_instock_sizes', 5 );
function display_instock_sizes() {
global $product;
if ( $product->is_type('variable') ) {
$taxonomy = 'stoerrelse'; // The product attribute taxonomy
$sizes_array = []; // Initializing
// Loop through available variation Ids for the variable product
foreach( $product->get_children() as $child_id ) {
$variation = wc_get_product( $child_id ); // Get the WC_Product_Variation object
if( $variation->is_purchasable() && $variation->is_in_stock() ) {
$term_name = $variation->get_attribute( $taxonomy );
$sizes_array[$term_name] = [$term_name => 'instock'];
}else{
$term_name = $variation->get_attribute( $taxonomy );
$sizes_array[$term_name] = [$term_name => 'outofstock'];
}
}
foreach ($sizes_array as $key => $value) {
if (empty($value)) {
unset($sizes_array[$key]);
}
}
if(empty($sizes_array)){
return;
}
ksort($sizes_array);
echo '<div class="attribute-size-wrapper">';
foreach ($sizes_array as $key => $value) {
foreach ($value as $key => $value) {
echo '<span class="attribute-size"><span class="'.$value.'">' . $key . '</span></span>';
}
}
echo '</div>';
}
}
when you are a new designer and start working with several content editors in wordpress, the first thing you realize is that it is not easy to find the functions you want exactly.
plugin editors can't think of everything.. and especially extract information to display them everywhere in the desired and consistent manner.
that's why wordpress shortcodes exist. but you have to master them.. first! (which is precisely my handicap currently)
Grab your cup of coffee ☕ and admire the detailed visual of today's issue
It will be very short and precise,
before starting look at what taxonomies we have in our post..
my current code allows me to do figure 1, as you can see it quickly becomes limited when you try to be .. more creative
add_shortcode( 'parent-child', 'taxonomy_hierarchy' );
function taxonomy_hierarchy( $atts ){
// Don't extract, rather parse shortcode params with defaults.
$atts = shortcode_atts( array(
'link' => 'true',
'taxonomy' => 'property_city'
), $atts, 'parent-child' );
// Check the $atts parameters and their typecasting.
//var_dump( $atts );
global $post;
$terms = wp_get_post_terms( $post->ID, $atts['taxonomy'] );
/* You can pass conditions here to override
* $link based on certain conditions. If it's
* a single post, current user is editor, etc.
*/
ob_start();
foreach( $terms as $term ){
if( $term->parent != 0 ){
$parent_term = get_term( $term->parent, $taxonomy );
if ($atts['link'] !== 'false') {
printf( '%s, ', esc_url( get_term_link($parent_term) ), $parent_term->name );
} else {
echo $parent_term->name . ', ';
}
}
if ($atts['link'] !== 'false') {
printf( '%s', esc_url( get_term_link($term) ), $term->name );
} else {
echo $term->name;
}
}
return ob_get_clean();
}
in this figure 1 we don't need to display "residential" and "rental" it doesn't make sense it's confusing. we don't have control over this.
but..What if I want to test and accomplish figure 2, figure 3 and figure 4
You : but there are already shortcodes what is it???
yes, don't worry, I took care to simulate a logic of things inside shortcodes, maybe that's not exactly how it's going to be. or how things work ..
I prefer to remain cautious and wait for your opinion or solution.
if logic allows, we need to separate the parent and childs values and paste them back as we want
like a puzzle
Something Like 👀
↑[taxonomy-parent = "name_of_my_taxonomy"]
↓[taxonomy-child = "name_of_my_taxonomy"]
or simply reverse in some cases
←[child-parent] (manhattan, new york)
→[parend-child] (new york, manhattan)
note that I used [acf field "name field here"] to invoke a price value, if it is possible to fit it inside our combination or leave it like that?
final word: you can tell I spent some time working out and thinking about this, if only coding was that easy for me I would have done even better. for now that's all I need more flexibility to display information in different ways.
You could consider using an array() instead to store the $parent if it exists, and then the $child which should exist. This would give you the benefit of being able to use array_reverse() to flip the order of the terms based on a parameter saying whether you want the parent or the child first. This gives you the added benefit of being able to convert the array to a string with the implode() function, which you can pass a $glue argument to, to determine whether you want them separated by a space, comma + space, hyphen, slash, etc.
add_shortcode( 'parent-child', 'taxonomy_hierarchy' );
function taxonomy_hierarchy( $atts ){
// Don't extract, rather parse shortcode params with defaults.
$atts = shortcode_atts( array(
'link' => 'true',
'glue' => ', ',
'taxonomy' => 'property_city',
'first' => 'parent',
), $atts, 'parent-child' );
// Check the $atts parameters and their typecasting.
//var_dump( $atts );
global $post;
$terms = wp_get_post_terms( $post->ID, $atts['taxonomy'] );
/* You can pass conditions here to override
* $link based on certain conditions. If it's
* a single post, current user is editor, etc.
*/
$array = array();
foreach( $terms as $term ){
if( $term->parent != 0 ){
$parent_term = get_term( $term->parent, $taxonomy );
if ($atts['link'] !== 'false') {
$array[] = sprintf( '%s', esc_url( get_term_link($parent_term) ), $parent_term->name );
} else {
$array[] = $parent_term->name;
}
}
if( $atts['link'] !== 'false' ){
$array = sprintf( '%s', esc_url( get_term_link($term) ), $term->name );
} else {
$array = $term->name;
}
}
if( $atts['first'] != 'parent' ){
$array = array_reverse( $array );
}
return implode($glue, $array);
}
Doing this should give you the ability to put out shortcodes like:
[parent-child first="child" glue=" - "] // Child - Parent
[parent-child glue="/"] // Parent/Child
Documentation & Function Reference
Function
Linked Description
array_reverse()
Return an array with elements in reverse order
implode()
Join array elements with a string
I think I found a solution but in this case it is no longer a shortcode with parameters.
it's become a bunch of shortcodes with a parameters, at least we have more flexibility now.
I simply cut the code into 3 parts
if you are not afraid to see 😰 very long complicated shortcodes. it's a solution that will help.
but I'm not sure if this is the best practice.
output taxonomy parent, child
/*output taxonomy parent, child*/
add_shortcode( 'parent-child', 'taxonomy_hierarchy' );
function taxonomy_hierarchy( $atts ){
$atts = shortcode_atts( array(
'link' => 'true',
'taxonomy' => 'property_city' // my default taxonomy
), $atts, 'parent-child' );
global $post;
$terms = wp_get_post_terms( $post->ID, $atts['taxonomy'] );
ob_start();
foreach( $terms as $term ){
if( $term->parent != 0 ){
$parent_term = get_term( $term->parent, $taxonomy );
if ($atts['link'] !== 'false') {
printf( '%s, ', esc_url( get_term_link($parent_term) ), $parent_term->name );
} else {
echo $parent_term->name . ', ';
}
}
if ($atts['link'] !== 'false') {
printf( '%s', esc_url( get_term_link($term) ), $term->name );
} else {
echo $term->name;
}
}
return ob_get_clean();
}
output only taxonomy parent
/*output only taxonomy parent*/
add_shortcode( 'parent', 'taxonomy_parent' );
function taxonomy_parent( $atts ){
$atts = shortcode_atts( array(
'link' => 'true',
'taxonomy' => 'property_city' // my default taxonomy
), $atts, 'parent' );
global $post;
$terms = wp_get_post_terms( $post->ID, $atts['taxonomy'] );
ob_start();
foreach( $terms as $term ){
if( $term->parent != 0 ){
$parent_term = get_term( $term->parent, $taxonomy );
if ($atts['link'] !== 'false') {
printf( '%s', esc_url( get_term_link($parent_term) ), $parent_term->name );
} else {
echo $parent_term->name;
}
}
}
return ob_get_clean();
}
output only taxonomy child
/*output only taxonomy child*/
add_shortcode( 'child', 'taxonomy_child' );
function taxonomy_child( $atts ){
$atts = shortcode_atts( array(
'link' => 'true',
'taxonomy' => 'property_city' // my default taxonomy
), $atts, 'child' );
global $post;
$terms = wp_get_post_terms( $post->ID, $atts['taxonomy'] );
ob_start();
foreach( $terms as $term ){
if ($atts['link'] !== 'false') {
printf( '%s', esc_url( get_term_link($term) ), $term->name );
} else {
echo $term->name;
}
}
return ob_get_clean();
}
I need to show only the primary category (a function added by default from YOAST) for a custom taxonomy in my template (wordpress).
The taxonomy is taken from the custom "course_category" in learnpress plugin.
It's a taxonomy that adds the categories into the courses created by the plugin.
I would like to create a function to call it in my loops, but i don't know how to write it properly for the custom taxonomies.
I found this code to use for standard categories (NOT FOR CUSTOM TAXONOMIES)
<?php
function get_primary_category( $post = 0 ) {
if ( ! $post ) {
$post = get_the_ID();
}
// SHOW YOAST PRIMARY CATEGORY, OR FIRST CATEGORY
$category = get_the_category( $post );
$primary_category = array();
// If post has a category assigned.
if ($category){
$category_display = '';
$category_slug = '';
$category_link = '';
$category_id = '';
if ( class_exists('WPSEO_Primary_Term') )
{
// Show the post's 'Primary' category, if this Yoast feature is available, & one is set
$wpseo_primary_term = new WPSEO_Primary_Term( 'category', get_the_id( $post ) );
$wpseo_primary_term = $wpseo_primary_term->get_primary_term();
$term = get_term( $wpseo_primary_term );
if (is_wp_error($term)) {
// Default to first category (not Yoast) if an error is returned
$category_display = $category[0]->name;
$category_slug = $category[0]->slug;
$category_link = get_category_link( $category[0]->term_id );
$category_id = $category[0]->term_id;
} else {
// Yoast Primary category
$category_display = $term->name;
$category_slug = $term->slug;
$category_link = get_category_link( $term->term_id );
$category_id = $term->term_id;
}
}
else {
// Default, display the first category in WP's list of assigned categories
$category_display = $category[0]->name;
$category_slug = $category[0]->slug;
$category_link = get_category_link( $category[0]->term_id );
$category_id = $term->term_id;
}
$primary_category['url'] = $category_link;
$primary_category['slug'] = $category_slug;
$primary_category['title'] = $category_display;
$primary_category['id'] = $category_id;
}
return $primary_category;
}
?>
which i can call later with
<?php echo '<pre>'.print_r(get_primary_category(get_the_ID()), true).'</pre>'; ?>
When removing terms from a post, delete terms which contain zero post. When updating a post, delete terms which contain zero post.
I have tried the code below, but it doesn't work:
add_filter('wp_remove_object_terms','delete_unused_terms');
function delete_unused_terms($term_ids, $taxonomy) {
foreach ( $term_ids as $term_id ) {
$term = get_term($term_id, $taxonomy);
$term_count = $term->count;
if ($term_count<1) {
wp_delete_term($term_id, $taxonomy);
}
}
}
Unfortunately, there is no wp_remove_object_terms filter.
But there is an action deleted_term_relationships;
Please, try to use
add_action( 'deleted_term_relationships', 'yuor_prefix_update_delete_term_if_empty', 10, 3 );
function yuor_prefix_update_delete_term_if_empty( $object_id, $term_ids, $taxonomy ) {
wp_update_term_count( $term_ids, $taxonomy );
foreach ( $term_ids as $term_id ) {
$term = get_term($term_id, $taxonomy);
$term_count = $term->count;
if ($term_count<1) {
wp_delete_term($term_id, $taxonomy);
}
}
}
I have problem with getting next and previous categories link and name in woocmmerce.
actually I found this but its just for normal wordpress categorys post..
I need next and prev for product category...any help..i'll appericated
I tryd below code but thats not logical at all...:
global $wp_query;
// get the query object
$cat = $wp_query->get_queried_object();
$cateID = $cat->term_id -1;
$termname = get_term_by( 'id', $cateID, 'product_cat' );
$plinkname = get_term_link( $cateID, 'product_cat' );
this will retrun +1 category Id..but for example it will not work when one of categroies deleted .
In functions.php:
function woocommerce_next_prev_link() {
if ( is_product_category() ){
$taxonomy = 'product_cat';
// Load all the terms for the product category
$terms = get_terms( array(
'taxonomy' => $taxonomy,
'hide_empty' => FALSE,
) );
// Put all of the category id's into a simple array for searching
$ids = array();
foreach( $terms as $term ) {
$ids[] = $term->term_id;
}
global $wp_query;
$cat_obj = $wp_query->get_queried_object();
// Load the current term ID from the current query
$this_term = $cat_obj->term_id;
// Find the term in the list of ID's
$this_position = array_search( $this_term, $ids );
// Identify the previous term
$prev_position = $this_position - 1;
// Identify the next term
$next_position = $this_position + 1;
// IF the previous term exists, and is not "off" the list (the currently displayed term is not the first term), then display the link
if( $prev_position >=0 ) {
$prev_id = array_slice( $ids, $prev_position, 1 );
$prev_term = get_term( $prev_id[0], $taxonomy );
if ( $prev_term ) {
echo '« ' . $prev_term->name . '';
}
}
// IF the next term exists, and is not "off" the list (the currently displayed term is not the last term), then display the link
if( $next_position > 0 && $next_position < count($ids) ) {
$next_id = array_slice( $ids, $next_position, 1 );
$next_term = get_term ($next_id[0], $taxonomy );
if ( $next_term ) {
echo '' . $next_term->name . ' »';
}
}
}
}
Call this fuction in your theme files:
woocommerce_next_prev_link();