For my WC product pages, I need to add a class to the body tag so that I can perform some custom styling. Here's the function I'm creating for this...
function my_add_woo_cat_class($classes) {
$wooCatIdForThisProduct = "?????"; //help!
// add 'class-name' to the $classes array
$classes[] = 'my-woo-cat-id-' . $wooCatIdForThisProduct;
// return the $classes array
return $classes;
}
//If we're showing a WC product page
if (is_product()) {
// Add specific CSS class by filter
add_filter('body_class','my_add_woo_cat_class');
}
...but how do I get the WooCommerce cat ID?
A WC product may belong to none, one or more WC categories. Supposing you just want to get one WC category id.
global $post;
$terms = get_the_terms( $post->ID, 'product_cat' );
foreach ($terms as $term) {
$product_cat_id = $term->term_id;
break;
}
Please look into the meta.php file in the "templates/single-product/" folder of the WooCommerce plugin.
<?php echo $product->get_categories( ', ', '<span class="posted_in">' . _n( 'Category:', 'Categories:', sizeof( get_the_terms( $post->ID, 'product_cat' ) ), 'woocommerce' ) . ' ', '.</span>' ); ?>
$product->get_categories() is deprecated since version 3.0! Use wc_get_product_category_list instead.
https://docs.woocommerce.com/wc-apidocs/function-wc_get_product_category_list.html
I literally striped out this line of code from content-single-popup.php located in woocommerce folder in my theme directory.
global $product;
echo $product->get_categories( ', ', ' ' . _n( ' ', ' ', $cat_count, 'woocommerce' ) . ' ', ' ' );
Since my theme that I am working on has integrated woocommerce in it, this was my solution.
Thanks Box. I'm using MyStile Theme and I needed to display the product category name in my search result page. I added this function to my child theme functions.php
Hope it helps others.
/* Post Meta */
if (!function_exists( 'woo_post_meta')) {
function woo_post_meta( ) {
global $woo_options;
global $post;
$terms = get_the_terms( $post->ID, 'product_cat' );
foreach ($terms as $term) {
$product_cat = $term->name;
break;
}
?>
<aside class="post-meta">
<ul>
<li class="post-category">
<?php the_category( ', ', $post->ID) ?>
<?php echo $product_cat; ?>
</li>
<?php the_tags( '<li class="tags">', ', ', '</li>' ); ?>
<?php if ( isset( $woo_options['woo_post_content'] ) && $woo_options['woo_post_content'] == 'excerpt' ) { ?>
<li class="comments"><?php comments_popup_link( __( 'Leave a comment', 'woothemes' ), __( '1 Comment', 'woothemes' ), __( '% Comments', 'woothemes' ) ); ?></li>
<?php } ?>
<?php edit_post_link( __( 'Edit', 'woothemes' ), '<li class="edit">', '</li>' ); ?>
</ul>
</aside>
<?php
}
}
?>
<?php
$terms = get_the_terms($product->ID, 'product_cat');
foreach ($terms as $term) {
$product_cat = $term->name;
echo $product_cat;
break;
}
?>
To add custom classes to the body tag you can use the body_class hook.
To add one or more classes on the product page based on specific product categories you can use the Wordpress has_term function (to check if a product belongs to that specific product category).
For this I created the array $classes_to_add where:
key: It can be the product category id (or the slug or the name). Or an array of them. Read the documentation.
value: a string containing the classes to add to the body tag. If you want to add more than one class create a string with multiple values separated by a space (see my example below)
So:
// adds a class to the body element based on the product category
add_filter( 'body_class', 'add_body_class_based_on_the_product_category' );
function add_body_class_based_on_the_product_category( $classes ) {
// only on the product page
if ( ! is_product() ) {
return $classes;
}
// create an array with the ids (or slugs) of the product categories and the respective class (or classes) to add
$classes_to_add = array(
30 => 'class-1',
'cat_slug' => 'class-2 class-3',
32 => 'class-4 class-5',
);
// if the product belongs to one of the product categories in the array it adds the respective class (or classes)
foreach ( $classes_to_add as $product_cat => $new_classes ) {
if ( has_term( $product_cat, 'product_cat', get_the_ID() ) ) {
$classes[] = $new_classes;
}
}
return $classes;
}
The code has been tested and works. Add it to your active theme's functions.php.
Related
I recently installed a plugin for wordpress/woocommerce that allows you to choose a primary category for a product when it's in multiple categories. It works well to change the breadcrumbs, but my theme (peakshops) also displays the primary category under the corresponding thumbnails on the the shop page.
This is the core function that is built into the theme to display the category (and link to the category) under the thumbnail:
// Add Title with Link.
function thb_template_loop_product_title() {
global $product;
$product_url = apply_filters( 'woocommerce_loop_product_link', get_the_permalink(), $product );
?>
<?php
if ( 'on' === ot_get_option( 'shop_product_listing_category', 'on' ) ) {
$shop_product_listing_category_single = ot_get_option( 'shop_product_listing_category_single', 'on' );
?>
<div class="product-category">
<?php
if ( 'on' === $shop_product_listing_category_single ) {
$product_cats = wc_get_product_category_list( get_the_ID(), '\n', '', '' );
if ( $product_cats ) {
list( $first_part ) = explode( '\n', $product_cats );
echo wp_kses(
$first_part,
array(
'a' => array(
'href' => array(),
'rel' => array(),
),
)
);
}
} else {
echo wc_get_product_category_list( $product->get_id(), ', ' );
}
?>
</div>
<?php } ?>
<h2 class="<?php echo esc_attr( apply_filters( 'woocommerce_product_loop_title_classes', 'woocommerce-loop-product__title' ) ); ?>"><?php the_title(); ?></h2>
<?php
}
add_action( 'woocommerce_shop_loop_item_title', 'thb_template_loop_product_title', 10 );
This core function seems to grab the first category rather than the primary category assigned by the plugin. Is there a way to change this action (or remove it and create a new one) so that it references the primary category assigned. For reference, the primary category plugin stores the value as a post meta field like this:
This code is outputting the Product (Brand) Category in (almost) the right spot - above the product title - on the Single Product Page.
How can I hyperlink it (Product Category) to the Product Category page? I essentially need to make this <?php echo $single_cat->name; ?> a dynamic hyperlink.
/** Output Product (Brand) Category on single product page **/
function add_brand_category(){
$product_cats = wp_get_post_terms( get_the_ID(), 'product_cat' );
if ( $product_cats && ! is_wp_error ( $product_cats ) ){
$single_cat = array_shift( $product_cats ); ?>
<h3 itemprop="name" class="product_category_title"><span><?php echo $single_cat->name; ?></span></h3>
<?php }
}
add_action( 'woocommerce_single_product_summary', 'add_brand_category', 2 );
You can use wc_get_product_category_list() – which returns the product categories in a list + adding a hyperlink to the product category page.
So you get:
function action_woocommerce_single_product_summary() {
global $product;
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
echo '<h3 itemprop="name" class="product_category_title">';
echo wc_get_product_category_list( $product->get_id(), ', ', '<span>' . _n( 'Category:', 'Categories:', count( $product->get_category_ids() ), 'woocommerce' ) . ' ', '</span>' );
echo '</h3>';
}
}
add_action( 'woocommerce_single_product_summary', 'action_woocommerce_single_product_summary', 2 );
I keep searching for a way to do this, but I can't find anything unfortunately.
I an trying to display all the product's attributes and values, separated by a pipe, in a custom place on the single-product (so for that I was thinking to create a shortcode, so I can place it anywhere I want). the output would be something like this:
BRAND: RENAULT | MODEL: 12 | YEAR: 1973
The code on the Woocommerce template product-attributes.php lists the attributes of the current product on single-product page, but it will list it with some styles I don't want in a place I don't want.
I want to create a shortcode with that code, which is:
<?php foreach ( $product_attributes as $product_attribute_key => $product_attribute ) : ?>
<?php echo wp_kses_post( $product_attribute['label'] ); ?>: <?php echo wp_kses_post( $product_attribute['value'] ); ?> |
<?php endforeach; ?>
How can I create a shortcode with it? I know the general code for a shortcode, but I don't know how to actually integrate the above one in it:
function custom_attributes_product_page() {
// integrate the required code
// Output needs to be return
return
}
// register shortcode
add_shortcode('custom-attributes', 'custom_attributes_product_page');
Would be great if this shortcode would list the attributes and their values separated by a column, like I said above (how to do that?)
Any help is highly appreciated.
Try the following shortcode that will display all product attribute(s) set for a product and their value(s), handling custom attributes too:
function get_product_attributes_shortcode($atts ) {
// Extract shortcode attributes
extract( shortcode_atts( array(
'id' => get_the_ID(),
), $atts, 'display-attributes' ) );
global $product;
if ( ! is_a($product, 'WC_Product') ) {
$product = wc_get_product( $id );
}
if ( is_a($product, 'WC_Product') ) {
$html = []; // Initializing
foreach ( $product->get_attributes() as $attribute => $values ) {
$attribute_name = wc_attribute_label($values->get_name());
$attribute_data = $values->get_data();
$is_taxonomy = $attribute_data['is_taxonomy'];
$option_values = array(); // Initializing
// For taxonomy product attribute values
if( $is_taxonomy ) {
$terms = $values->get_terms(); // Get attribute WP_Terms
// Loop through attribute WP_Term(s)
foreach ( $terms as $term ) {
$term_link = get_term_link( $term, $attribute );
$option_values[] = ''.$term->name.'';
}
}
// For "custom" product attributes values
else {
// Loop through attribute option values
foreach ( $values->get_options() as $term_name ) {
$option_values[] = $term_name;
}
}
$html[] = '<strong>' . $attribute_name . '</strong>: ' . implode(', ', $option_values);
}
return '<div class="product-attributes">' . implode(' | ', $html) . '<div>';
}
}
add_shortcode( 'display-attributes', 'get_product_attributes_shortcode' );
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
USAGE: [display-attributes] or with a defined product Id [display-attributes id="254"]
You will get a display like: BRAND: RENAULT | MODEL: 12 | YEAR: 1973
If you don't want the linked terms, replace:
$term_link = get_term_link( $term, $attribute );
$option_values[] = ''.$term->name.'';
by this:
$option_values[] = $term->name;
I've added the following snippet to display a custom field (that don't display taxonomy field if product has field) with the estimated delivery time. This is working.
<?php add_action( 'woocommerce_before_add_to_cart_form', 'geschatte_levertijd', 10 );
function geschatte_levertijd (){
if( get_field('plevertijd') ): ?>
<span class="product_melding_kleur"><i class="fa fa-truck"></i>Levertijd: <a href="/verzending-en-levertijd/" alt="Verzending en levertijd" ><?php the_field( 'plevertijd' ); ?></a></span>
<?php else: ?>
<? $terms = get_the_terms( $post->ID, 'product_cat' );
if ( !empty($terms)):
$term = array_pop($terms);
$text= get_field('levertijd', $term);
if (!empty($levertijd))?>
<span class="product_melding_kleur"><i class="fa fa-truck"></i>Levertijd: <a href="/verzending-en-levertijd/" alt="Verzending en levertijd" ><?php the_field( 'levertijd', $term ); ?></a></span>
<?php endif; ?>
<?php endif;
}
?>
But now I'm trying to display that field inside the order notification mail. Below the product title.
Could someone point me into the right direction on how to do that?
The following will use your code to make happen the display in order email notifications under order item product name:
add_action( 'woocommerce_order_item_meta_start', 'add_estimated_delivery_time_to_emails', 10, 3 );
function add_estimated_delivery_time_to_emails( $item_id, $item, $order ) {
// On email notifications and for line items
if ( ! is_wc_endpoint_url() && $item->is_type('line_item') ) {
if( $plevertijd = get_field('plevertijd', $item->get_product_id() ) ) {
echo '<span class="product_melding_kleur"><i class="fa fa-truck"></i>Levertijd: <a href="/verzending-en-levertijd/" alt="Verzending en levertijd" >' . $plevertijd . '</a></span>';
} else {
$terms = get_the_terms( $item->get_product_id(), 'product_cat' );
if ( ! empty($terms) ) {
$term = array_pop( $terms );
if( $levertijd = get_field('levertijd', $term ) ) {
echo '<span class="product_melding_kleur"><i class="fa fa-truck"></i>Levertijd: <a href="/verzending-en-levertijd/" alt="Verzending en levertijd" >' . $levertijd . '</a></span>';
}
}
}
}
}
Code goes in functions.php file of your active child theme (or active theme). It should works.
Displaying on frontend orders:
If you want that to be displayed on customer order (front end), you can remove from the IF statement the following: ! is_wc_endpoint_url() &&
You can also use the woocommerce_order_item_meta_end hook instead, to get the display after the product attributes on product variations.
I would like to change the Text of the related products, which is at the end of the product detail page. At the moment I'm displaying This could be interesting by using this code
<h2><?php esc_html_e( 'This could be interesting', 'woocommerce' ); ?></h2>
What I would like to display is Our favorite category name
I tried to expand the code with this snippet, without any success
<?php echo wc_get_product_category_list($product->get_id()) ?>
How is it possible to get this function done?
Here is a little helper function that you could put in your functions.php
function get_favorite_category_title_for( $product_id ) {
$title = __('This could be interesting', 'woocommerce');
$cats = wp_get_post_terms( $product_id, 'product_cat' );
if( count($cats) > 0 ) {
$title = __( 'Our favorite ', 'woocommerce' ) . $cats[0]->name;
}
return $title;
}
and then replace the h2 tag with:
<h2><?php echo get_favorite_category_title_for( get_queried_object_id() ); ?></h2>
you can change get_queried_object_id with the $product->get_id() if you have access to $product object.