I display the breadcrumbs inside my product pages. I am trying to manually replace the category link of "Horlogerie" with a custom link '/test'.
Here is my code using this answer :
add_filter( 'woocommerce_get_breadcrumb', 'custom_breadcrumb', 10, 2 );
function custom_breadcrumb( $crumbs, $object_class ){
// Loop through all $crumb
var_dump($crumbs);
foreach( $crumbs as $key => $crumb ){
$taxonomy = 'product_cat'; // The product category taxonomy
// Check if it is a product category term
$term_array = term_exists( $crumb[0], $taxonomy );
// if it is a product category term
if ( $term_array !== 0 && $term_array !== null ) {
// Get the WP_Term instance object
$term = get_term( $term_array['term_id'], $taxonomy );
// HERE set your new link with a custom one
$crumbs[$key][1] = 'test';
}
}
return $crumbs;
}
But the link doesn't get changed. I tried using the "Twenty Twenty-one" theme, but the problem persists.
Thank you for your help.
You have simply just added one condition. try the below code.
function custom_breadcrumb( $crumbs, $object_class ){
// Loop through all $crumb
var_dump($crumbs);
foreach( $crumbs as $key => $crumb ){
$taxonomy = 'product_cat'; // The product category taxonomy
// Check if it is a product category term
$term_array = term_exists( $crumb[0], $taxonomy );
// if it is a product category term
if ( $term_array !== 0 && $term_array !== null ) {
// Get the WP_Term instance object
$term = get_term( $term_array['term_id'], $taxonomy );
if( $term->name == 'your specific term name' ){
// HERE set your new link with a custom one
$crumbs[$key][1] = 'test';
}
}
}
return $crumbs;
}
add_filter( 'woocommerce_get_breadcrumb', 'custom_breadcrumb', 10, 2 );
Related
Please pardon me if there's a better way to do this as I am not very familiar with this code. I would like to display only the link to the homepage and the current product on the breadcrumb.
Desire result:
Currently:
I found the code for the breadcrumb, is there a way to only display the first and last crumb regardless of the hierarchy?
foreach ( $breadcrumb as $key => $crumb ) {
echo $before;
if ( ! empty( $crumb[1] ) && sizeof( $breadcrumb ) !== $key ) {
echo '' . esc_html( $crumb[0] ) . '';
} else if(!is_product() && !flatsome_option('wc_category_page_title')) {
echo esc_html( $crumb[0] );
}
echo $after;
// Single product or Active title
if(is_product() || flatsome_option('wc_category_page_title')){
$key = $key+1;
if ( sizeof( $breadcrumb ) > $key) {
echo ' <span class="divider">'.$delimiter.'</span> ';
}
} else{
// Category pages
if ( sizeof( $breadcrumb ) !== $key + 1 ) {
echo ' <span class="divider">'.$delimiter.'</span> ';
}
}
}
The reason why I am doing this is that some of the products have multiple categories and by default, it will only show the breadcrumb for the primary category. I would rather make a truncated version as suggested by the owner.
I was also wondering if I can simply dynamically retrieve the product title and link + static homepage link, make it into a shortcode so that I can paste it in the product page.
Hi – the first example in the answer above, also removes the shop from woocommerce breadcrumb. Here is a working example, that only removes the category:
// remove only the category from woocommerce breadcrumbs
add_filter( 'woocommerce_get_breadcrumb', 'custom_breadcrumb', 20, 2 );
function custom_breadcrumb( $crumbs, $breadcrumb ) {
//print the array and look for the key with the category
//echo '<pre>';
//print_r($crumbs);
//echo '</pre>';
//unset($crumbs[2]); in my case it is key 2
// only on the single product page
if ( ! is_product() ) {
return $crumbs;
} else {
unset($crumbs[2]); // this isn't enough, it would leave a trailing delimiter
$newBreadC = array_values($crumbs); //therefore create new array
return $newBreadC; //return the new array
}
}
If you want to remove categories and subcategories from product breadcrumbs on the product page you can use the woocommerce_get_breadcrumb hook.
// change the breadcrumb on the product page
add_filter( 'woocommerce_get_breadcrumb', 'custom_breadcrumb', 20, 2 );
function custom_breadcrumb( $crumbs, $breadcrumb ) {
// only on the single product page
if ( ! is_product() ) {
return $crumbs;
}
// gets the first element of the array "$crumbs"
$new_crumbs[] = reset( $crumbs );
// gets the last element of the array "$crumbs"
$new_crumbs[] = end( $crumbs );
return $new_crumbs;
}
The code has been tested and works. Add it to your active theme's functions.php.
A good alternative is to set the primary product category for each product. You can do this by installing the Yoast SEO plugin.
You can use the _yoast_wpseo_primary_product_cat product meta to set the id of the primary product category.
After setting the primary category id by editing the product in the
backend or importing a .csv file you will only need to change the
permalink and breadcrumbs based on the primary product category.
To update the product permalink:
// update the product permalink based on the primary product category
add_filter( 'wc_product_post_type_link_product_cat', 'change_product_permalink_by_cat', 10, 3 );
function change_product_permalink_by_cat( $term, $terms, $post ) {
// get the primary term as saved by Yoast
$primary_cat_id = get_post_meta( $post->ID, '_yoast_wpseo_primary_product_cat', true );
// if there is a primary and it's not currently chosen as primary
if ( $primary_cat_id && $term->term_id != $primary_cat_id ) {
// find the primary term in the term list
foreach ( $terms as $term_key => $term_object ) {
if ( $term_object->term_id == $primary_cat_id ) {
// return this as the primary term
$term = $terms[ $term_key ];
break;
}
}
}
return $term;
}
To update the product breadcrumbs on the product page:
// change the breadcrumb on the product page
add_filter( 'woocommerce_get_breadcrumb', 'custom_breadcrumb', 20, 2 );
function custom_breadcrumb( $crumbs, $breadcrumb ) {
// only on the single product page
if ( ! is_product() ) {
return $crumbs;
}
global $product;
$new_crumbs = array();
if ( $product->get_meta( '_yoast_wpseo_primary_product_cat', true ) ) {
// gets the first element of the array "$crumbs"
$new_crumbs[] = reset( $crumbs );
// gets the id of the primary product category
$primary_cat_id = $product->get_meta( '_yoast_wpseo_primary_product_cat', true );
// create an array with all parent categories (based on the id of the primary product category)
$parent_categories = get_ancestors( $primary_cat_id, 'product_cat' );
$parent_categories = array_reverse($parent_categories);
$parent_categories[] = $primary_cat_id;
// for each product category it gets the name and the permalink
foreach ( $parent_categories as $cat_id ) {
$term = get_term_by( 'id', $cat_id, 'product_cat' );
$new_crumbs[] = array(
0 => $term->name,
1 => esc_url( get_term_link( $term, 'product_cat' ) )
);
}
// gets the last element of the array "$crumbs"
$new_crumbs[] = end( $crumbs );
} else {
// gets the first element of the array "$crumbs"
$new_crumbs[] = reset( $crumbs );
// gets the last element of the array "$crumbs"
$new_crumbs[] = end( $crumbs );
}
return $new_crumbs;
}
The code has been tested and works. Add it to your active theme's functions.php.
I want to change the WooCommerce product description tab button and title "Description" into "Tracklist" when the page has a body class of "parent-product_cat-vinyl".
Here is my code so far:
<?php
if ( is_singular() ) {
$classes = get_body_class();
if (in_array('parent-product_cat-vinyl',$classes)) {
add_filter( 'woocommerce_product_description_tab_title','ps_rename_description_product_tab_label');
function ps_rename_description_product_tab_label() {
return 'Tracklist';
}
}
}
But it doesn't seem to work.
You can use the following composite filter hooks (where $tab_key is in your case description):
woocommerce_product_{$tab_key}_tab_title
woocommerce_product_{$tab_key}_heading
It can be done in 2 ways:
Conditionally with a defined body class:
add_filter( 'woocommerce_product_description_tab_title', 'change_product_description_tab_text' );
add_filter( 'woocommerce_product_description_heading', 'change_product_description_tab_text' );
function change_product_description_tab_text( $title ) {
global $product;
if( in_array( 'parent-product_cat-vinyl', get_body_class() ) ) {
return __('Tracklist', 'woocommerce');
}
return $title;
}
Or conditionally for a product category (including parent product categories):
// Custom conditional function that handle parent product categories too
function has_product_categories( $categories, $product_id = 0 ) {
$parent_term_ids = $categories_ids = array(); // Initializing
$taxonomy = 'product_cat';
$product_id = $product_id == 0 ? get_the_id() : $product_id;
if( is_string( $categories ) ) {
$categories = (array) $categories; // Convert string to array
}
// Convert categories term names and slugs to categories term ids
foreach ( $categories as $category ){
$result = (array) term_exists( $category, $taxonomy );
if ( ! empty( $result ) ) {
$categories_ids[] = reset($result);
}
}
// Loop through the current product category terms to get only parent main category term
foreach( get_the_terms( $product_id, $taxonomy ) as $term ){
if( $term->parent > 0 ){
$parent_term_ids[] = $term->parent; // Set the parent product category
$parent_term_ids[] = $term->term_id; // (and the child)
} else {
$parent_term_ids[] = $term->term_id; // It is the Main category term and we set it.
}
}
return array_intersect( $categories_ids, array_unique($parent_term_ids) ) ? true : false;
}
add_filter( 'woocommerce_product_description_tab_title', 'change_product_description_tab_text' );
add_filter( 'woocommerce_product_description_heading', 'change_product_description_tab_text' );
function change_product_description_tab_text( $title ) {
global $product;
// Here set in the array the targeted product categories
$categories = array('Vinyl');
if ( has_product_categories( $categories, $product->get_id() ) ) {
return __('Tracklist', 'woocommerce');
}
return $title;
}
Code goes in functions.php file of your active child theme (or active theme) . Tested and works.
In woocommerce I am using Hide “remove item” from cart for WooCommerce product category answer code and I would like to disable the cart quantity field too, avoiding customer to change the item quantity to zero.
Is that possible? Any track on this will be appreciated.
The following code will remove the "quantity field" from cart for items from a specific product category (that you will define in the 2nd function):
// Custom conditional function that handle parent product categories too
function has_product_categories( $categories, $product_id = 0 ) {
$parent_term_ids = $categories_ids = array(); // Initializing
$taxonomy = 'product_cat';
$product_id = $product_id == 0 ? get_the_id() : $product_id;
if( is_string( $categories ) ) {
$categories = (array) $categories; // Convert string to array
}
// Convert categories term names and slugs to categories term ids
foreach ( $categories as $category ){
$result = (array) term_exists( $category, $taxonomy );
if ( ! empty( $result ) ) {
$categories_ids[] = reset($result);
}
}
// Loop through the current product category terms to get only parent main category term
foreach( get_the_terms( $product_id, $taxonomy ) as $term ){
if( $term->parent > 0 ){
$parent_term_ids[] = $term->parent; // Set the parent product category
$parent_term_ids[] = $term->term_id; // (and the child)
} else {
$parent_term_ids[] = $term->term_id; // It is the Main category term and we set it.
}
}
return array_intersect( $categories_ids, array_unique($parent_term_ids) ) ? true : false;
}
add_filter( 'woocommerce_quantity_input_args', 'hide_cart_quantity_input_field', 20, 2 );
function hide_cart_quantity_input_field( $args, $product ) {
// HERE your specific products categories
$categories = array( 'clothing' );
// Handling product variation
$product_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();
// Only on cart page for a specific product category
if( is_cart() && has_product_categories( $product_id, $categories ) ){
$input_value = $args['input_value'];
$args['min_value'] = $args['max_value'] = $input_value;
}
return $args;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Note: If you are using also your other answer code, the first function is already defined and doesn"t have to be twice on your function php file…
I would like to Hide "remove item" from cart for a specific product category in WooCommerce, just like in "Hide "remove item" from cart for a specific product in WooCommerce" answer thread, but for a specific product category.
Any help would be appreciated.
The following code will hide "remove item" from cart for a specific product category (that you will define in the 2nd function):
// Custom conditional function that handle parent product categories too
function has_product_categories( $categories, $product_id = 0 ) {
$parent_term_ids = $categories_ids = array(); // Initializing
$taxonomy = 'product_cat';
$product_id = $product_id == 0 ? get_the_id() : $product_id;
if( is_string( $categories ) ) {
$categories = (array) $categories; // Convert string to array
}
// Convert categories term names and slugs to categories term ids
foreach ( $categories as $category ){
$result = (array) term_exists( $category, $taxonomy );
if ( ! empty( $result ) ) {
$categories_ids[] = reset($result);
}
}
// Loop through the current product category terms to get only parent main category term
foreach( get_the_terms( $product_id, $taxonomy ) as $term ){
if( $term->parent > 0 ){
$parent_term_ids[] = $term->parent; // Set the parent product category
$parent_term_ids[] = $term->term_id; // (and the child)
} else {
$parent_term_ids[] = $term->term_id; // It is the Main category term and we set it.
}
}
return array_intersect( $categories_ids, array_unique($parent_term_ids) ) ? true : false;
}
// Hiding "remove item" for specific product category
add_filter('woocommerce_cart_item_remove_link', 'filter_cart_item_remove_link', 20, 2 );
function filter_cart_item_remove_link( $button_link, $cart_item_key ){
// HERE your specific products categories
$categories = array( 'clothing' );
// Get the current cart item
$cart_item = WC()->cart->get_cart()[$cart_item_key];
// If the targeted product is in cart we remove the button link
if( has_product_categories( $cart_item['product_id'], $categories ) )
$button_link = '';
return $button_link;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
The below code will work as you want it : just change the category id in if clause:
function tristup_woocommerce_cart_item_remove_link($link){
preg_match('/data-product_id=\"(.*?)\"/', $link, $matches);
$flag=0;
if($matches)
{
$product_id=$matches[1];
$terms = get_the_terms ( $product_id, 'product_cat' );
foreach ( $terms as $term )
{
if($term->term_id=='210') // change with your category id or add more with in proper syntaxes
{
return '';
}
}
}
return $link;
}
add_filter('woocommerce_cart_item_remove_link', 'tristup_woocommerce_cart_item_remove_link');
In Woocommerce I have a Product Attribute called "Platform" the Value of the Attribute is "Steam":
So I am bulk importing the products and the Attributes are already there.
But now I have to set for every product manually the category.
Is it possible to set the Value automatically as Product Category in a function?
This Function is returning me the Attribute value right?
function get_attribute_value_from_name( $name ){
global $wpdb;
$name = 'Platform';
$attribute_value = $wpdb->get_var("SELECT attribute_value
FROM {$wpdb->prefix}woocommerce_attribute_taxonomies
WHERE attribute_name LIKE '$name'");
return $attribute_value;
}
And now how to set the value for product category?
EDIT:
$product = wc_get_product($id); //LOAD PRODUCT
global $product_attribute; //VARIABLE
$product_attribute = $product->get_attribute( 'Platform' ); //GET ATTRIBUTE OF PLATFORM
wp_set_object_terms( $post_id, $product_attribute, 'product_cat' ); //WRITE IT AS CATEGORY
$product->save(); //SAVE PRODUCT
does this make sense?
Update 2 - To set an existing product category term in a product (using a defined product ID):
// Get an instance of the WC_Product object
$product = wc_get_product( $product_id );
$term_names = $product->get_attribute( 'Platform' ); // Can have many term names (coma separated)
$term_names = explode( ',', $term_names);
$term_ids = [];
// Loop through the terms
foreach( $term_names as $term_name ) {
// Get the term ID and check if it exist
if( $term_id = term_exists( $term_name, 'product_cat' ) ) {
// Add each term ID in an array
$term_ids[] = $term_id;
}
}
// Append the product category terms in the product
if( sizeof($term_ids) > 0 ) {
$product->set_category_ids( $term_ids );
$product->save();
}
Here below is an example of a hooked function that will auto set the product category terms on product edit.
Note: the product category terms need to exist in woocommerce
// Backend product creation
add_action( 'woocommerce_admin_process_product_object', 'add_product_category_terms_to_product', 100, 1 );
function add_product_category_terms_to_product( $product ){
global $pagenow;
// Only on product Edit
if( $pagenow != 'post.php' ) return; // Exit
if( $term_names = $product->get_attribute( 'Platform' ) )
$term_names = explode( ',', $term_names);
else
return; // Exit
$term_ids = [];
// Loop through the terms
foreach( $term_names as $term_name ) {
// Get the term ID and check if it exist
if( $term_id = term_exists( $term_name, 'product_cat' ) ) {
// Add each term ID in an array
$term_ids[] = $term_id;
}
}
// replace the product categories terms in the product
if( sizeof($term_ids) > 0 ) {
$product->set_category_ids( $term_ids );
}
// save is not needed in the function as this hook does that
}
Code goes in function.php file of your active child theme (or active theme). It should works.