Woocommerce breadcrumbs multiple categories - php

I have e commerce website in wordpress. There are lot of product in it & many product comes under multiple categories like 600 mah Power bank is comes under automobile, IT, media etc. My problem is when i go to the detail of a product there it by default pick up only one category no matter if go through IT category at the end it shows me automobile like this Home / Shop / industry / Automobile / 600 mah Power Bank. But i went to this product via IT so it should show me like this Home / Shop / industry / IT / 600 mah Power Bank.
How can iget path where i come from previous page?

if you are using Woocommerce you can use the following directly, if not it will need adapting but you get the idea:
if (get_post_type() == 'product' && is_single() && ! is_attachment()) {
echo $prepend;
if ($terms = get_the_terms($post->ID, 'product_cat')) {
$referer = wp_get_referer();
foreach ($terms as $term) {
$referer_slug = (strpos($referer, $term->slug));
if ($referer_slug == true) {
$category_name = $term->name;
$ancestors = get_ancestors($term->term_id, 'product_cat');
$ancestors = array_reverse($ancestors);
foreach ($ancestors as $ancestor) {
$ancestor = get_term($ancestor, 'product_cat');
if (! is_wp_error($ancestor) && $ancestor) {
echo $before . '' . $ancestor->name . '' . $after . $delimiter;
}
}
echo $before . '' . $category_name . '' . $after . $delimiter;
}
}
}
echo $before . get_the_title() . $after;
}
The main bulk of the work here is done by wp_get_referer which gets the referring URL of the product your visitor has navigated to. The rest of the code checks if a valid category is contained within the URL and uses it in the breadcrumb.
See Jonathon Js post here for more information http://www.cryoutcreations.eu/forums/t/wrong-breadcrumbs-displayed

Updated answer for anyone still encountering this issue on a newer version of WooCommerce, this solution worked for me on WooCommerce 3.5.4.
This code should be placed inside the following file path (i.e. a child theme)
/wp-content/themes/your-child-theme/woocommerce/global/breadcrumb.php
It will override the default WooCommerce breadcrumb code.
http://pastebin.com/raw/bemM8ZNF
/**
* Shop breadcrumb
*
* This template can be overridden by copying it to yourtheme/woocommerce/global/breadcrumb.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* #see https://docs.woocommerce.com/document/template-structure/
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.3.0
* #see woocommerce_breadcrumb()
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( $breadcrumb ) {
echo $wrap_before;
if ( is_single() && get_post_type() == 'product' ) {
echo $prepend;
if ( $terms = get_the_terms( $post->ID, 'product_cat' ) ) {
$referer = wp_get_referer();
$printed = array();
foreach( $terms as $term){
if(in_array($term->id, $printed)) continue;
$referer_slug = (strpos($referer, '/'.$term->slug.'/'));
if(!$referer_slug==false){
$printed[] = $term->id;
$category_name = $term->name;
$ancestors = get_ancestors( $term->term_id, 'product_cat' );
$ancestors = array_reverse( $ancestors );
foreach ( $ancestors as $ancestor ) {
$ancestor = get_term( $ancestor, 'product_cat' );
if ( ! is_wp_error( $ancestor ) && $ancestor )
echo $before . '' . $ancestor->name . '' . $after . $delimiter;
}
echo $before . '' . $category_name . '' . $after . $delimiter;
}
}
}
echo $before . get_the_title() . $after;
} else {
foreach ( $breadcrumb as $key => $crumb ) {
echo $before;
if ( ! empty( $crumb[1] ) && sizeof( $breadcrumb ) !== $key + 1 ) {
echo '' . esc_html( $crumb[0] ) . '';
} else {
echo esc_html( $crumb[0] );
}
echo $after;
if ( sizeof( $breadcrumb ) !== $key + 1 ) {
echo $delimiter;
}
}
}
echo $wrap_after;
}
C/O: Joris Witteman

I reworked the code a little bit to account for a primary category and a referred one, having infinite parents.
I used the breadcrumb filter as it is quite clean, directly in the single product template, but in case you need it elsewhere you can use the single conditional.
function breadcumbs_referred_or_primary ($main, $terms)
{
// Our primary term is 520 (hardcoded)
$referer = wp_get_referer();
$referredTerm = -1;
$referredTermIndex = -1;
$primaryTermId = 520; // hardcoded
$primaryTermIndex = -1;
foreach($terms as $key => $term) {
if ($referredTerm != -1) break; // we found it in a previous iteration!
$ancestors = get_ancestors( $term->term_id, 'product_cat');
array_unshift($ancestors, $term->term_id);
if ($primaryTermIndex == -1 && in_array($primaryTermId, $ancestors)) $primaryTermIndex = $key;
foreach ($ancestors as $ancestor) {
if($referredTerm != -1) break 2; // we found it in a previous iteration!
$ancestor = get_term( $ancestor, 'product_cat' );
$referer_slug = (strpos($referer, '/'.$ancestor->slug.'/'));
if (!$referer_slug==false) { // it's found in the current level
$referredTerm = $term->term_id;
$referredTermIndex = $key;
}
}
}
// we return either the browsed terms or the primary term
if ($referredTermIndex != -1) {
return $terms[$referredTermIndex];
} else {
return $terms[$primaryTermIndex];
}
}
add_filter('woocommerce_breadcrumb_main_term', 'breadcumbs_referred_or_primary', 10, 2);

My solution is:
if (!empty($breadcrumb)) {
echo $wrap_before;
if (is_single() && get_post_type() == 'product') {
$breadcrumb_diff = [];
$breadcrumb_diff[] = $breadcrumb[0];
if ($terms = get_the_terms($post->ID, 'product_cat')) {
$referer = wp_get_referer();
$site_url = site_url();
$referer = str_replace($site_url . '/zoomagazin/', '', $referer);
$referer_array = explode('/', $referer);
foreach ($referer_array as $term_slug) {
$get_term_by_slug = get_term_by('slug', $term_slug, 'product_cat');
$breadcrumb_diff[] = [$get_term_by_slug->name, get_term_link($term_slug, 'product_cat')];
}
$breadcrumb_diff[]= $breadcrumb[count($breadcrumb) - 1];
foreach ($breadcrumb_diff as $key => $crumb) {
echo $before;
if (!empty($crumb[1]) && sizeof($breadcrumb_diff) !== $key + 1) {
echo '' . esc_html($crumb[0]) . '';
} else {
echo esc_html($crumb[0]);
}
echo $after;
if (sizeof($breadcrumb) !== $key + 1) {
echo $delimiter;
}
}
}
} else {
foreach ($breadcrumb as $key => $crumb) {
echo $before;
if (!empty($crumb[1]) && sizeof($breadcrumb) !== $key + 1) {
echo '' . esc_html($crumb[0]) . '';
} else {
echo esc_html($crumb[0]);
}
echo $after;
if (sizeof($breadcrumb) !== $key + 1) {
echo $delimiter;
}
}
}
echo $wrap_after;
}

Related

WooCommerce - Remove product title from breadcrumbs but keep all category hyperlinks

I'm using the following function to remove the product title from the breadcrumbs displayed on the product page:
add_filter( 'woocommerce_get_breadcrumb', 'ed_change_breadcrumb' );
function ed_change_breadcrumb( $breadcrumb ) {
if(is_singular()){
array_pop($breadcrumb);
}
return $breadcrumb;
}
It works in that it does remove the title, but it also stops the last category/sub-category from being a hyperlink. How can I fix that?
For example:
Original breadcrumb
<a>Home</a> / <a>Category</a> / <a>Sub Category</a> / Product Title
Result of the above function
<a>Home</a> / <a>Category</a> / Sub Category
I need the Sub Category to still be clickable after removing the product title from the breadcrumbs.
Thanks
Your code works but the last element in the breadcrumbs never contains a link through the code used in global/breadcrumb.php template file on line 34
This template can be overridden by copying it to yourtheme/woocommerce/global/breadcrumb.php.
So you can remove your filter hook and apply the following code in the template file so that it provides a link to the last element when is_product() is true
Note: is_product() - Returns true on a single product page. Wrapper for is_singular()
Replace
if ( ! empty( $breadcrumb ) ) {
echo $wrap_before;
foreach ( $breadcrumb as $key => $crumb ) {
echo $before;
if ( ! empty( $crumb[1] ) && sizeof( $breadcrumb ) !== $key + 1 ) {
echo '' . esc_html( $crumb[0] ) . '';
} else {
echo esc_html( $crumb[0] );
}
echo $after;
if ( sizeof( $breadcrumb ) !== $key + 1 ) {
echo $delimiter;
}
}
echo $wrap_after;
}
With
if ( ! empty( $breadcrumb ) ) {
echo $wrap_before;
foreach ( $breadcrumb as $key => $crumb ) {
echo $before;
if ( ! empty( $crumb[1] ) && sizeof( $breadcrumb ) !== $key + 1 ) {
echo '' . esc_html( $crumb[0] ) . '';
} else {
if ( is_product() ) {
unset($crumb);
} else {
echo esc_html( $crumb[0] );
}
}
echo $after;
if ( sizeof( $breadcrumb ) !== $key + 1 ) {
if ( is_product() && sizeof( $breadcrumb ) == $key + 2 ) {
echo '';
} else {
echo $delimiter;
}
}
}
echo $wrap_after;
}

Adding "Home" at the beginning of breadcrumbs

I'm having issues formatting the breadcrumbs on my staging site. I had them set up with the correct categories before, but the parent category kept displaying the wrong category (which I did fix, but...). The fix caused the "home" option to disappear. I don't know any php and have been trying without success to figure out how to add a "Home /" option on each page before the category. Below is the code I'm using now. Anyone have any ideas?
if ( ! empty( $breadcrumb ) ) {
echo $wrap_before;
if ( is_single() && get_post_type() == 'product' ) {
echo $prepend;
if ( $terms = get_the_terms( $post->ID, 'product_cat' ) ) {
$referer = wp_get_referer();
$printed = array();
foreach( $terms as $term){
if(in_array($term->id, $printed)) continue;
$referer_slug = (strpos($referer, '/'.$term->slug.'/'));
if(!$referer_slug==false){
$printed[] = $term->id;
$category_name = $term->name;
$ancestors = get_ancestors( $term->term_id, 'product_cat' );
$ancestors = array_reverse( $ancestors );
foreach ( $ancestors as $ancestor ) {
$ancestor = get_term( $ancestor, 'product_cat' );
if ( ! is_wp_error( $ancestor ) && $ancestor )
echo $before . '' . $ancestor->name . '' . $after . $delimiter;
}
echo $before . '' . $category_name . '' . $after . $delimiter;
}
}
}
echo $before . get_the_title() . $after;
} else {
foreach ( $breadcrumb as $key => $crumb ) {
echo $before;
if ( ! empty( $crumb[1] ) && sizeof( $breadcrumb ) !== $key + 1 ) {
echo '' . esc_html( $crumb[0] ) . '';
} else {
echo esc_html( $crumb[0] );
}
echo $after;
if ( sizeof( $breadcrumb ) !== $key + 1 ) {
echo $delimiter;
}
}
}
echo $wrap_after;
}
Thanks for the help in advance!
I think you can achieve this by changing the following line echo $wrap_before; to this:
echo $wrap_before.'Home »';

How to display all custom product attributes with variations in WooCommerce

This code shows how to display custom product attributes for without variations. I wish to display all the variations too in the typical dropdown select menu. How do I do that?
P/S: I can't post the code here because this site says I have too much code and too little details.
UPDATED:
/**
* Show all product attributes on the product page
*/
function isa_woocommerce_all_pa(){
global $product;
$attributes = $product->get_attributes();
if ( ! $attributes ) {
return;
}
$out = '';
foreach ( $attributes as $attribute ) {
// skip variations
if ( $attribute->get_variation() ) {
continue;
}
$name = $attribute->get_name();
if ( $attribute->is_taxonomy() ) {
$terms = wp_get_post_terms( $product->get_id(), $name, 'all' );
// get the taxonomy
$tax = $terms[0]->taxonomy;
// get the tax object
$tax_object = get_taxonomy($tax);
// get tax label
if ( isset ($tax_object->labels->singular_name) ) {
$tax_label = $tax_object->labels->singular_name;
} elseif ( isset( $tax_object->label ) ) {
$tax_label = $tax_object->label;
// Trim label prefix since WC 3.0
if ( 0 === strpos( $tax_label, 'Product ' ) ) {
$tax_label = substr( $tax_label, 8 );
}
}
$out .= $tax_label . ': ';
$tax_terms = array();
foreach ( $terms as $term ) {
$single_term = esc_html( $term->name );
array_push( $tax_terms, $single_term );
}
$out .= implode(', ', $tax_terms) . '<br />';
} else {
$out .= $name . ': ';
$out .= esc_html( implode( ', ', $attribute->get_options() ) ) . '<br />';
}
}
echo $out;
}
add_action('woocommerce_single_product_summary', 'isa_woocommerce_all_pa', 25);

Remove "Shop" from BreadCrumb in WooCommerce

How to Remove Shop Text from Bread Crumb in woo commerce?[Home-->Shop-->Pink Himalayan Salt]
I want to Set Bread crumb as per my Navigation menu in m WordPress site.[Home-->Products-->Salt-->Pink Himalayan Salt]
I have used some Pages, Custom Links, Categories & Products to My main Menu.
See screenshot.
Bredcrumb -
Menu -
You can override WooCommerce templates via the theme (read the following official documentation):
Template Structure + Overriding Templates via a Theme
Once you have copied the file from plugins/woocommerce/templates/global/breadcrumb.php
to: themes/yourtheme/woocommerce/global/breadcrumb.php, you will be able to change the code by replacing it with the following:
<?php
/**
* Shop breadcrumb
*
* This template can be overridden by copying it to yourtheme/woocommerce/global/breadcrumb.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* #see https://docs.woocommerce.com/document/template-structure/
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.3.0
* #see woocommerce_breadcrumb()
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! empty( $breadcrumb ) ) {
$breadcrumb0 = $breadcrumb[0];
$shop_txt = __( 'Shop', 'woocommerce' );
$products_txt = __( 'Products', 'woocommerce' );
$products_url = home_url( '/products/' );
$breadcrumb10 = array( $products_txt );
$breadcrumb11 = array( $products_txt, $products_url );
if(is_product() || is_shop() || is_product_category() || is_product_tag() ){
if( $breadcrumb[1][0] == $shop_txt ){
if( ! empty( $breadcrumb[1][1] ) )
$breadcrumb[1] = $breadcrumb11;
else
$breadcrumb[1] = $breadcrumb10;
} else {
unset($breadcrumb[0]);
array_unshift($breadcrumb, $breadcrumb0, $breadcrumb11);
}
}
echo $wrap_before;
foreach ( $breadcrumb as $key => $crumb ) {
echo $before;
if ( ! empty( $crumb[1] ) && sizeof( $breadcrumb ) !== $key + 1 ) {
echo '' . esc_html( $crumb[0] ) . '';
} else {
echo esc_html( $crumb[0] );
}
echo $after;
if ( sizeof( $breadcrumb ) !== $key + 1 ) {
echo $delimiter;
}
}
echo $wrap_after;
}
This will:
Replace "Shop" by "Products"
Add "Products" just after "Home" when "Shop" doesn't exits.
So your breadcrumps will always start with: Home > Products on shop, archives and single product pages…
This might be solved with CSS, but cannot help unless you post a link to your shop.
Try like this:
Add this line to your custom CSS
ul.breadcrumbs li:nth-of-type(2) {display:none}
If it does not work, might also need !important
ul.breadcrumbs li:nth-of-type(2) {display:none!important}
I cannot comment that is why I had to answer. please provide the link of your site. I'll update my answer with exact CSS.
Inspired by LoicTheAztec, here is a solution for a similar but slightly different requirement. Let's say you just wanted to remove the Shop link completely:
Copy the file: plugins/woocommerce/templates/global/breadcrumb.php
to: themes/yourtheme/woocommerce/global/breadcrumb.php
In the new file, look for the line
foreach ( $breadcrumb as $key => $crumb ) {
and after that line, add this line:
if (trim(strip_tags($crumb[0])) == 'Shop') { continue; }
So the final code will look like this:
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! empty( $breadcrumb ) ) {
echo $wrap_before;
foreach ( $breadcrumb as $key => $crumb ) {
if (trim(strip_tags($crumb[0])) == 'Shop') { continue; }
echo $before;
if ( ! empty( $crumb[1] ) && sizeof( $breadcrumb ) !== $key + 1 ) {
echo '' . esc_html( $crumb[0] ) . '';
} else {
echo esc_html( $crumb[0] );
}
echo $after;
if ( sizeof( $breadcrumb ) !== $key + 1 ) {
echo $delimiter;
}
}
echo $wrap_after;
}
I have Got the answer by doing changes on functions.php
https://www.screencast.com/t/U42lqPduY707
if (get_post_type() == 'product')
{
echo sprintf($link, '#', esc_html__('Products', 'thegem'));
//echo sprintf($link, get_permalink(get_option ('woocommerce_shop_page_id' , 0 )), esc_html__('Product', 'thegem'));
$taxonomy = 'product_cat';
$terms = get_the_terms( $post->ID, $taxonomy );
foreach ( $terms as $c ) {
$c->term_id;
// echo '' . ($c->name ) . '';
if($c->term_id=='36') {
echo $delimiter;
echo sprintf($link, get_permalink( 106 ), esc_html__($c->name, 'thegem'));
}
}
}
else {
$slug = $post_type->rewrite;
printf($link, $home_link . '/' . $slug['slug'] . '/', $post_type->labels->singular_name);
}

Display atributes value and name in cart woocomerce

Simple question how to display product atributes in cart woocomerce: for example color:red, not sure if there is some code to add like hook or some code to fundctions.php or it can be done through woocomerce settings, have not found any useful information online, any help is appreciated.
Just do a simple things as follows, you will get all in your cart_item -
add_filter('woocommerce_cart_item_name', 'add_variations_in_cart', 10, 3);
function add_variations_in_cart($name, $cart_item, $item_key){
$product_variation = '';
if(!empty($cart_item['variation_id']) && $cart_item['variation_id'] != 0 ){
if(is_array($cart_item['variation']) && !empty($cart_item['variation'])){
foreach ($cart_item['variation'] as $key => $value) {
$product_variation .= '<br>'.ucfirst(str_replace('attribute_pa_', '', $key)).' : '.ucfirst($value);
}
}
}
echo $name.$product_variation;
}
as simple as that. Thank you.
tyr this plugin https://wordpress.org/plugins/woocommerce-show-attributes/
OR
WooCommerce: show all product attributes listed below each item on Cart page
add this below code in function.php
/**
* WooCommerce: show all product attributes listed below each item on Cart page
*/
function sm_woo_cart_attributes($cart_item, $cart_item_key){
$item_data = $cart_item_key['data'];
$attributes = $item_data->get_attributes();
if ( ! $attributes ) {
return $cart_item;
}
$out = $cart_item . '<br />';
foreach ( $attributes as $attribute ) {
if ( $attribute['is_taxonomy'] ) {
// skip variations
if ( $attribute['is_variation'] ) {
continue;
}
// backwards compatibility for attributes which are registered as taxonomies
$product_id = $item_data->id;
$terms = wp_get_post_terms( $product_id, $attribute['name'], 'all' );
// get the taxonomy
$tax = $terms[0]->taxonomy;
// get the tax object
$tax_object = get_taxonomy($tax);
// get tax label
if ( isset ($tax_object->labels->name) ) {
$tax_label = $tax_object->labels->name;
} elseif ( isset( $tax_object->label ) ) {
$tax_label = $tax_object->label;
}
foreach ( $terms as $term ) {
$out .= $tax_label . ': ';
$out .= $term->name . '<br />';
}
} else {
// not a taxonomy
$out .= $attribute['name'] . ': ';
$out .= $attribute['value'] . '<br />';
}
}
echo $out;
}
add_filter( 'woocommerce_cart_item_name', sm_woo_cart_attributes, 10, 2 );

Categories