I want to add some attributes to the shop page of wordpress.
This code i found on Stackoverflow, is shows all attribute labes but on all the same attribute names.
add_action('woocommerce_after_shop_loop_item_title','add_attribute');
function add_attribute() {
global $product;
$product_attributes = array( 'pa_country','pa_class','pa_faction','pa_gender' );
$attr_output = array();
foreach( $product_attributes as $taxonomy ){
if( taxonomy_exists($taxonomy) ){
$label_name = get_taxonomy( $taxonomy )->labels->singular_name;
$value = $product->get_attribute('pa_country','pa_class','pa_faction','pa_gender');
if( ! empty($value) ){
$attr_output[] = '<span class="'.$taxonomy.'">'.$label_name.': '.$value.'</span>';
}
}}
echo '<div class="product-attributes">'.implode( '<br>', $attr_output ).'</div>';
}
current state
I just need a bit help to get it to show all the right attributes.
There a some little mistakes in your code. Try the following instead:
add_action('woocommerce_after_shop_loop_item_title', 'display_shop_loop_product_attributes');
function display_shop_loop_product_attributes() {
global $product;
// Define you product attribute taxonomies in the array
$product_attribute_taxonomies = array( 'pa_country', 'pa_class', 'pa_faction', 'pa_gender' );
$attr_output = array(); // Initializing
// Loop through your defined product attribute taxonomies
foreach( $product_attribute_taxonomies as $taxonomy ){
if( taxonomy_exists($taxonomy) ){
$label_name = wc_attribute_label( $taxonomy, $product );
$term_names = $product->get_attribute( $taxonomy );
if( ! empty($term_names) ){
$attr_output[] = '<span class="'.$taxonomy.'">'.$label_name.': '.$term_names.'</span>';
}
}
}
// Output
echo '<div class="product-attributes">'.implode( '<br>', $attr_output ).'</div>';
}
Code goes in functions.php file of your active child theme (or active theme). tested and works.
For simple products only you will use the following instead:
add_action('woocommerce_after_shop_loop_item_title', 'display_shop_loop_product_attributes');
function display_shop_loop_product_attributes() {
global $product;
// Only for simple products
if ( ! $product->is_type( 'simple' ) ) return;
// Define you product attribute taxonomies in the array
$product_attribute_taxonomies = array( 'pa_country', 'pa_class', 'pa_faction', 'pa_gender' );
$attr_output = array(); // Initializing
// Loop through your defined product attribute taxonomies
foreach( $product_attribute_taxonomies as $taxonomy ){
if( taxonomy_exists($taxonomy) ){
$label_name = wc_attribute_label( $taxonomy, $product );
$term_names = $product->get_attribute( $taxonomy );
if( ! empty($term_names) ){
$attr_output[] = '<span class="'.$taxonomy.'">'.$label_name.': '.$term_names.'</span>';
}
}
}
// Output
echo '<div class="product-attributes">'.implode( '<br>', $attr_output ).'</div>';
}
Code goes in functions.php file of your active child theme (or active theme). tested and works.
I solved the problem. its not pretty but it works.
add_action( 'woocommerce_after_shop_loop_item_title', 'display_size_attribute', 5 );
function display_size_attribute() {
global $product;
if ( $product->is_type('simple') ) {
$taxonomy = 'pa_country';
echo '<span class="attribute-s">Country: ' . $product->get_attribute($taxonomy) . '</span>','<br>';
}
if ( $product->is_type('simple') ) {
$taxonomy = 'pa_class';
echo '<span class="attribute-s">Class: ' . $product->get_attribute($taxonomy) . '</span>','<br>';
}
if ( $product->is_type('simple') ) {
$taxonomy = 'pa_faction';
echo '<span class="attribute-s">Faction: ' . $product->get_attribute($taxonomy) . '</span>','<br>';
}
if ( $product->is_type('simple') ) {
$taxonomy = 'pa_gender';
echo '<span class="attribute-s">Gender: ' . $product->get_attribute($taxonomy) . '</span>','<br>';
}}
Related
I am using WooCommerce and I want to get the current product attribute URL to be used on the single product page, replacing the code <category_url>/?filter_preco= by the URL.
Here is my code:
add_action( 'woocommerce_single_product_summary', 'cj_show_attribute_links', 4 );
function cj_show_attribute_links() {
global $post, $product;
$attribute_names = array( 'pa_preco' ); // Insert attribute names here
foreach ( $attribute_names as $attribute_name ) {
$taxonomy = get_taxonomy( $attribute_name );
if ( $taxonomy && ! is_wp_error( $taxonomy ) ) {
$terms = wp_get_post_terms( $post->ID, $attribute_name );
$terms_array = array();
if ( ! empty( $terms ) ) {
foreach ( $terms as $term ) {
$archive_link = $term->slug;
$base = '<category_url>?filter_preco=';
$full_line = '<h4 style="font-size: 15px; color: #4E4E4E;">'. $term->name . '</h4><div class="is-divider small"></div>';
array_push( $terms_array, $full_line );
}
echo ' ' . implode( $terms_array);
}
}
}
}
Any idea?
There are some mistakes in your code… Use this replacement code that uses get_term_link() WordPress function to get the term link as follows:
add_action( 'woocommerce_single_product_summary', 'display_linked_product_attributes', 4 );
function display_linked_product_attributes() {
global $post, $product;
$taxonomy = array( 'pa_preco' ); // Here define product attribute(s) taxonomy(ies)
foreach ( $attribute_names as $attribute_name ) {
$terms = wp_get_post_terms( get_the_ID(), $taxonomy );
$output = '';
foreach ( $terms as $term ) {
$link = get_term_link( $term, $taxonomy );
$output .= '<h4 style="font-size: 15px; color: #4E4E4E;">'. $term->name . '</h4><div class="is-divider small"></div>';
}
echo ' ' . $output;
}
}
Code goes in functions.php file of the active child theme (or active theme). It should better work.
I got the solution by using this (I am getting a error when the product has no category)
function pagina_produto_embaixo_titulo() {
global $post;
$attribute_names = array( 'pa_preco' ); // Insert attribute names here
foreach ( $attribute_names as $attribute_name ) {
$taxonomy = get_taxonomy( $attribute_name );
if ( $taxonomy && ! is_wp_error( $taxonomy ) ) {
$terms = wp_get_post_terms( $post->ID, $attribute_name );
$terms_array = array();
if ( ! empty( $terms ) ) {
foreach ( $terms as $term ) {
$archive_link = $term->slug;
$terms = get_the_terms( $post->ID, 'product_cat' );
$link = get_term_link( $terms[0]->term_id, 'product_cat' );
$base = $link .'?filter_preco=';
//erro nas 2 linhas acima, quando o produto nao tem categoria, e na pagina da loja, deixa de funcuonar algus coisas.
$full_line = '<h4 style="font-size: 15px; color: #4E4E4E;">O que é µStar+? | '. $term->name . '</h4><div>';
array_push( $terms_array, $full_line );
}
echo ' ' . implode( $terms_array);
}
}
}
}
Need to display the product shipping class to product page! any ideas why this is not working?
add_action('woocommerce_single_product_summary', 'display_product_shipping_class', 15 );
function display_product_shipping_class(){
global $product;
$term = get_term_by( 'slug', $product->get_product_shipping_class(), 'product_shipping_class' );
if( is_a($term, 'WP_Term') && $term->name == $product_shipping_class ){
echo '<p class="product-shipping-class">' . $term->name . '</p>';
}
}
There are multiple mistakes in your code. Try the following instead:
add_action('woocommerce_single_product_summary', 'display_product_shipping_class', 15 );
function display_product_shipping_class(){
global $product;
$shipping_class = $product->get_shipping_class();
if( ! empty($shipping_class) ) {
$term = get_term_by( 'slug', $shipping_class, 'product_shipping_class' );
if( is_a($term, 'WP_Term') ){
echo '<p class="product-shipping-class">' . $term->name . '</p>';
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
I need an imploded list of terms from three custom Woocommerce taxonomies including the taxonomy name to display in the product loop. I'll also need to be able to display multiple terms for each taxonomy. However, I can only get it to work with one taxonomy. And I can't figure out how to display the corresponding taxonomy name.
My custom taxonomies are 'artists', 'illustrators' and 'authors'. Here's what I'm trying to accomplish:
Robert Douglas (Author), Bill Johnston (Illustrator), Kyle McBeth (Artist)
function list_author_terms() {
global $post;
$person = get_the_terms(get_the_ID(), 'authors', 'artists', 'illustrators');
if ( $person
&& !is_wp_error( $person )
) {
#usort( $person, function ( $a, $b )
{
return strcasecmp(
$a->slug,
$b->slug
);
});
// Display your terms as normal
$term_list = [];
foreach ( $person as $term )
$term_list[] = '' . esc_html( $term->name ) . '<span class="attribute"> (Author)</span> ';
$term_names[] = $term->name;
echo implode( ', ', $term_list);
echo '<br>';
}
}
Add follows code snippet to achieve your task -
add_action( 'woocommerce_after_shop_loop_item', 'list_author_terms', 6 );
function list_author_terms(){
$taxonomies = array( 'authors', 'artists', 'illustrators' );
$pro_list_terms = array();
foreach ( $taxonomies as $taxonomy ) {
$term_obj_list = get_the_terms( get_the_ID(), $taxonomy );
$tax_obj = get_taxonomy( $taxonomy );
if( $term_obj_list && ! is_wp_error( $term_obj_list ) ){
foreach ( $term_obj_list as $term ) {
$link = get_term_link( $term, $taxonomy );
$pro_list_terms[] = '' . $term->name . ' (' .$tax_obj->labels->singular_name . ')';
}
}
}
echo join( ', ', $pro_list_terms );
}
I am trying to accomplish a attribute and term list on the shop page using the hook woocommerce_shop_loop_item_title. The goal is to get the attribute(s) and term(s) for the product and then to display it like this example:
Color: Red, Blue, Green
Size: Small, Medium, Large
Dimensions: 90*90, 100*100 and 120*120
but without the spaces between the rows.
It should "fetch" all the attributes used with the product and the attributes terms.
I've tried this but got fatal error.
add_action( 'woocommerce_shop_loop_item_title', 'variable_att_and_terms_on_loop');
function variable_att_and_terms_on_loop() {
foreach( $product->get_variation_attributes() as $taxonomy => $terms_slug ) {
$taxonomy_label = wc_attribute_label( $taxonomy, $product );
foreach($terms_slug as $term) {
$term_name = get_term_by('slug', $term, $taxonomy)->name;
$attributes_and_terms_names[$taxonomy_label][$term] = $term_name;
}
}
foreach ( $attributes_and_terms_names as $attribute_name => $terms_name ) {
$terms_string = implode( ', ', $terms_name );
echo '<p>' . $attribute_name . ': ' . $terms_string . '</p>';
}
}
I've also tried this:
add_action('woocommerce_shop_loop_item_title','add_attribute', 5);
function add_attribute() {
global $product;
$product_attributes = array( 'pa_weight', 'pa_quantity', 'pa_length', 'pa_color' );
$attr_output = array();
foreach( $product_attributes as $taxonomy ){
if( taxonomy_exists($taxonomy) ){
$label_name = get_taxonomy( $taxonomy )->labels->singular_name;
$value = $product->get_attribute('pa_weight');
if( ! empty($value) ){
$attr_output[] = '<span class="'.$taxonomy.'">'.$label_name.': '.$value.'</span>';
}
}
}
echo '<div class="product-attributes">'.implode( '<br>', $attr_output ).'</div>';
}
without any result.
After trying the new result below from LoicTheAztec, this is what I get:
Uppdate 2020 - Removed an error when trying to get the term name from a term slug.
In your first code snippet there are some mistakes:
the $product variable was not defined
The function needed to be restricted to variable products only
the $attributes_and_terms_names variable was not initialized…
Here is the revisited code (without the spaces between the rows):
add_action( 'woocommerce_shop_loop_item_title', 'variable_att_and_terms_on_loop');
function variable_att_and_terms_on_loop() {
global $product;
if( ! $product->is_type('variable') ) return; // Only for variable products
$variation_attributes = $product->get_variation_attributes();
if( sizeof($variation_attributes ) == 0 ) return; // Exit if empty
$attributes = array(); // Initializing
foreach( $product->get_variation_attributes() as $taxonomy => $terms_slug ) {
$taxonomy_label = wc_attribute_label( $taxonomy, $product );
$terms_name = array();
foreach($terms_slug as $term_slug ) {
// We try to get the term name when it's a term slug
$term = get_term_by('slug', $term_slug, $taxonomy);
$terms_name[] = ! is_a($term, 'WP_Term') ? $term_slug : $term->name;
}
$attributes[] = $taxonomy_label . ': ' . implode( ', ', $terms_name );
}
echo '<div class="product-attributes">';
echo '<span>' . implode('</span><br><span>', $attributes) . '</span>';
echo '</div>';
}
Code goes in function.php file of your active child theme (active theme). Tested and works.
Bellow I have a custom shortcode function based on this answer code that displays a block of product data for both Simple products and each variation of a Variable product. The output of the variation blocks seems to be ordered by the ID of the variation itself.
For example, this is a screenshot of the frontend output:
Which you can see matches the order of the variation IDs (from smallest to largest) screenshot:
What I would like is to sort the variations by their prices instead (NOT by their IDs) from lowest to highest. Any help is appreciated.
This is the current customized code that I have:
add_shortcode("price_variation_table", "fs_custom_available_variations_table");
function fs_custom_available_variations_table( $atts ) {
global $post;
// Attributes
$atts = shortcode_atts(
array(
'id' => $post->ID
),
$atts, 'price_variation_table'
);
if( is_admin() ) return; // Only on front end
$product = wc_get_product($atts['id']); // Get the WC_Product Object
$output = '<div class="fs-product-data-wrapper">';
// Variable products
if( $product->is_type('variable'))
{
// Get available variations in the variable product
$available_variations = $product->get_available_variations();
if( count($available_variations) > 0 ){
foreach( $available_variations as $variation )
$output .= fs_format_product_data_output( $variation['variation_id'] );
}
}
// Simple products
elseif( $product->is_type('simple'))
{
$output .= fs_format_product_data_output( $product->get_id() );
}
else return; // Exit
return $output .= '</div>'; // return always for a shortcode
}
// Utility funtion: getting and formtting product data
function fs_format_product_data_output( $the_id ){
$empty = __( '<em>(empty)</em>', 'woocommerce' );
// Get an instance of the WC_Product_Variation object
$product = wc_get_product( $the_id );
// Only wc_get_price_to_display() respect if product is to be displayed with or without including taxes
$price = wc_price( wc_get_price_to_display( $product, array( 'price' => $product->get_regular_price() ) ) );
$sale_price = wc_get_price_to_display( $product, array( 'price' => $product->get_sale_price() ) );
$sale_price = ! empty( $sale_price ) ? wc_price($sale_price) : $empty;
// can use this class is there is no sale price set
if ( ! $product->is_on_sale() ) {
$no_sale_price = ' no-sale-price';
}
$size = $product->get_attribute( 'pa_size' );
$size = ! empty( $size ) ? get_term_by( 'slug', $size, 'pa_size' )->name : $empty;
$stock_qty = $product->get_stock_quantity();
$stock_qty = ! empty( $stock_qty ) ? $stock_qty : '0';
if ( $stock_qty <= 0 ) {
$stock_status = 'stock-sold-out';
}
else {
$stock_status = 'stock-available';
}
$output = '
<ul class="'. $stock_status .'">
<li class="fs-data-price">'.$price.' ea.</li>
<li class="fs-data-size">Size: '.$size.'</li>
<li class="fs-data-sale'. $no_sale_price .'">'.$sale_price.' ea. Preferred customer price</li>
<li class="fs-data-stock">Quantity in Stock: '.$stock_qty.'</li>
<li class="fs-data-notice">Quantities change quickly!</li>
</ul>';
return $output;
}
Try the following lightly changed code, where each displayed variations will be sorted by regular price (low to high):
add_shortcode("price_variation_table", "custom_available_variations_table");
function custom_available_variations_table( $atts ) {
global $post;
// Attributes
$atts = shortcode_atts(
array(
'id' => $post->ID
),
$atts, 'price_variation_table'
);
if( is_admin() ) return; // Only on front end
$product = wc_get_product($atts['id']); // Get the WC_Product Object
$output = '<div class="fs-product-data-wrapper">';
// Variable products
if( $product->is_type('variable'))
{
// Get available variations in the variable product
$available_variations = $product->get_available_variations();
if( count($available_variations) > 0 ){
$variations_ids = array();
// First loop - set variations Ids in an array with regular prices
foreach( $available_variations as $variation ){
$product = wc_get_product( $variation['variation_id'] );
$price = wc_price( wc_get_price_to_display( $product, array( 'price' => $product->get_regular_price() ) ) );
$variations_ids[$variation['variation_id']] = $price;
}
// Sorting variation Ids using prices from lower to highest
natsort($variations_ids);
// 2nd Loop - Display formatted variation data
foreach( array_keys($variations_ids) as $variations_id ){
$output .= format_product_data_output( $variations_id );
}
}
}
// Simple products
elseif( $product->is_type('simple'))
{
$output .= format_product_data_output( $product->get_id() );
}
else return; // Exit
return $output .= '</div>'; // return always for a shortcode
}
// Utility funtion: getting and formatting product data
function format_product_data_output( $the_id ){
$empty = __( '<em>(empty)</em>', 'woocommerce' );
// Get an instance of the WC_Product_Variation object
$product = wc_get_product( $the_id );
// Only wc_get_price_to_display() respect if product is to be displayed with or without including taxes
$price = wc_price( wc_get_price_to_display( $product, array( 'price' => $product->get_regular_price() ) ) );
$sale_price = wc_get_price_to_display( $product, array( 'price' => $product->get_sale_price() ) );
$sale_price = ! empty( $sale_price ) ? wc_price($sale_price) : $empty;
$size = $product->get_attribute( 'pa_size' );
$size = ! empty( $size ) ? get_term_by( 'slug', $size, 'pa_size' )->name : $empty;
$no_sale_price = ! $product->is_on_sale() ? ' no-sale-price' : '';
$size = $product->get_attribute( 'pa_size' );
$size = ! empty( $size ) ? get_term_by( 'slug', $size, 'pa_size' )->name : $empty;
$stock_qty = $product->get_stock_quantity();
$stock_qty = ! empty( $stock_qty ) ? $stock_qty : '0';
$stock_status = $stock_qty <= 0 ? 'stock-sold-out' : 'stock-available';
$output = '
<ul class="'. $stock_status .'">
<li class="fs-data-price">'.$price.' ea.</li>
<li class="fs-data-size">Size: '.$size.'</li>
<li class="fs-data-sale'. $no_sale_price .'">'.$sale_price.' ea. Preferred customer price</li>
<li class="fs-data-stock">Quantity in Stock: '.$stock_qty.'</li>
<li class="fs-data-notice">Quantities change quickly!</li>
</ul>';
return $output;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.