This is my code for display an atributte below a product title. How can I display it like a link to archive page of this attributte?
add_action( 'woocommerce_single_product_summary', 'custom_template_single_title', 5 );
function custom_template_single_title() {
global $product;
$brand_name = $product->get_attribute('Autor');
echo '<div class ="author-product">';
if( $brand_name )
echo $brand_name;
echo '</div>';
}
First, $product->get_attribute('Autor') can give multiple coma separated term names.
Below, we add the term link to each term name (if there is more than one):
add_action( 'woocommerce_single_product_summary', 'custom_template_single_title', 5 );
function custom_template_single_title() {
global $product;
$taxonomy = 'pa_autor'; // <== The product attribute taxonomy
$linked_terms = []; // Initializing
if ( $term_names = $product->get_attribute($taxonomy) ) {
// Loop through the term names
foreach( explode(', ', $term_names) as $term_name ) {
$term_id = get_term_by('name', $term_name, $taxonomy)->term_id; // get the term ID
$term_link = get_term_link( $term_id, $taxonomy ); // get the term link
$linked_terms[] = '' . $term_name . '';
}
// Output
echo '<div class ="author-product">' . implode(', ', $linked_terms) . '</div>';
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Related
I'm building a shop in WP + WooCommerce. I have different types of product categories like discs and bags. For discs products I have some specific attributes like Speed, Glide, Turn and Fade that don't have any other product categories. I want to display these product attribute values only on shop pages under the product picture.
I have found one code for that and I added myself a separation symbol "|", but this separation symbol is now displayed under all the products that are variable.
Is it possible to change the code not to variables but only for specific product categories and sub-categories?
Code:
add_action( 'woocommerce_before_shop_loop_item_title', 'display_size_attribute', 5 );
function display_size_attribute() {
global $product;
if ( $product->is_type('variable') ) {
$taxonomy = 'pa_speed';
echo '<span class="attribute-speed">' . $product->get_attribute($taxonomy) . '</span>' ;
echo ' | ';
$taxonomy = 'pa_Glide';
echo '<span class="attribute-Glide">' . $product->get_attribute($taxonomy) . '</span>';
echo ' | ';
$taxonomy = 'pa_Turn';
echo '<span class="attribute-Turn">' . $product->get_attribute($taxonomy) . '</span>';
echo ' | ';
$taxonomy = 'pa_Fade';
echo '<span class="attribute-Fade">' . $product->get_attribute($taxonomy) . '</span>';
}
}
Use the following revisited code instead to get separated attribute values only if they exist on your variable products:
add_action( 'woocommerce_before_shop_loop_item_title', 'display_some_attributes', 5 );
function display_some_attributes() {
global $product;
if ( $product->is_type('variable') ) {
$attributes = array('speed', 'Glide', 'Turn', 'Fade'); // here you defined attribute slugs
$output = array(); // Initializing
// Loop through product attributes
foreach ( $attributes as $attribute ) {
$taxonomy = 'pa_' . $attribute;
$values = $product->get_attribute($taxonomy);
// If not empty add it to the array
if ( ! empty($values) ) {
$output[] = '<span class="attribute-' . $attribute . '">' . $values . '</span>';
}
}
// Convert array to a separated string by pipes
echo implode(' | ', $output);
}
}
To target specific product categories only, replace in the code the block:
global $product;
if ( $product->is_type('variable') ) {
with (where you will define your product categories terms):
global $product;
$categories = array( 'cats', dogs' ); // Here your category terms ids, slugs or names
if ( $product->is_type('variable') && has_term( $categories, 'product_cat', $product->get_id() ) ) {
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
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;
Is there any way to replace range price of variable products in woocommerce on shop page and instead of it showing a list of variations and their prices per product in order to display variations to customer and showing 'Add to Cart' for all type of products not 'Choose an Option' for variable products.
I have tested a lot of code snippets without success.
Below code is the closest to what I need, I used code suggested here Get specific product attribute name and value for each WooCommerce variation of a variable product and changed it. but still the problem is that part of attribute is not shown.
add_filter( 'woocommerce_variable_price_html', 'custom_variable_price_html', 10, 2 );
function custom_variable_price_html( $price, $product ) {
if(!is_admin()){
if(is_shop()){
$product_attribute_slug = 'ابعاد-فرش';
$targeted_taxonomy = 'pa_' . $product_attribute_slug;
$available_variations = $product->get_available_variations();
$output = '<div>';
foreach( $available_variations as $variation_data ){
if( $variation_data['display_price'] === $variation_data['display_regular_price'] ) {
$price_to_display = wc_price( $variation_data['display_price'] );
} else {
$variation = wc_get_product($variation_data['variation_id']); // Get the WC_Product_Variation Object
$price_to_display = wc_get_price_to_display( $variation, array('price' => $variation->get_sale_price() ) );
}
foreach ( $variation_data['attributes'] as $variation_attribute => $term_slug ) {
// Get the taxonomy slug
$taxonomy = str_replace( 'attribute_', '', $variation_attribute );
// Get the correct product attribute term value for this variation
if( $taxonomy === $targeted_taxonomy ) {
// Get the attribute value term name
$term_name = get_term_by( 'slug', $term_slug, $taxonomy )->name;
}
}
$output .= '<span>' . $term_name . ':' . wc_attribute_label( $targeted_taxonomy ) . ':' . strip_tags($price_to_display) . '</span><br>';
}
$output .= '</div>';
$price = $output;
return $price;
} else {
return $price;
}
} else {
return $price;
}
}
what I get is:
but I need something Like this:
As I noticed
$term_name
variable in code is empty.
Any help is appreciated.
Solution: set taxonomy as follow and use it in get_term_by() function:
$taxonomy = 'pa_ابعاد-فرش';
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.
In a Wordpress + Woocommerce website I have a menu with some custom links that recall specific shop pages URLs using advanced queries taxonomies.
These are example links I use for these custom menu entries:
https://example.com/product-category/cat1/?pa_attrib1=value1&pa_attrib2=value3
https://example.com/product-category/cat2/?pa_attrib1=value2&pa_attrib3=value4`
https://example.com/product-category/cat2/?pa_attrib1=value5&pa_attrib4=value5,value7,value8,value9
In this way I can configure "direct" entries to the various shop departments.
Now I need to show, in the shop and archive page, the name and the values of the attributes set in the url in a similar way:
Category Name - Attribute 1 name: value1 - Atttribute 2 Name: value2, ...
I suppose I need to use the hook woocommerce_archive_description in functions.php but I don't know how recall and show the values I need
add_action ( 'woocommerce_archive_description', 'show_term_description', 20 );
function show_term_description() {
echo term_description( $term_id, $taxonomy ); // print Category Name
// ...
// ...
}
thanks
This can be done with the following commented code inserted in your hooked function:
add_action ( 'woocommerce_archive_description', 'show_term_description', 20 );
function show_term_description() {
// Only for product category archive pages
if( ! is_product_category()) return;
global $wp;
// Get the requested Url category/subcategories
$request = $wp->request;
// Set them in an array
$request = explode( '/', $request );
// Remove 'product-category' from the array
if( 'product-category' == $request[0] )
unset($request[0]);
// Starting html formatting
$html = '<p><strong>';
// The main category and sub-categories names
foreach( $request as $category ){
// Get the category name
$category_term = get_term_by( 'slug', $category, 'product_cat' );
// Set category and subcategories in an array
$categories_name[] = $category_term->name;
}
// Formatting the category/subcategories in an html string
$html .= implode( '</strong> - <strong>', $categories_name );
// The product attributes names and related values
if( ! empty($_GET) ){
$html .= '</strong> - <strong>'; // Formatting html
$count = 0; // Initializing the counter
$attr_count = count($_GET); // get the length of the array
// Loop through the attribute/values from the $_GET
foreach($_GET as $taxonomy => $values ){
$count++;
$terms_names = array(); // Initializing
// If the taxonomy doesn't exist,
if( ! taxonomy_exists( $taxonomy ) ){
continue; // We go to next attribute
}
// Set the attribute terms in an array
$term_slugs = explode( ',', $values );
// Loop through the attribute term
foreach( $term_slugs as $term_slug ){
// Get the WP_Term object
$term = get_term_by( 'slug', $term_slug, $taxonomy );
if( ! term_exists( $term->term_id, $taxonomy ) )
continue; // We go to next term
// Set The term name in an array
$terms_names[] = $term->name;
}
// If there is no corresponding terms for the taxonomy
if( sizeof($terms_names) == 0 ){
continue; // We go to next attribute
}
// Add the attribute label name to the output
if( $count > 1 ) $html .= ' - ';
$html .= wc_attribute_label( $taxonomy );
// Formatting the term names in a string and add them to the output
$html .= ':</strong> ' . implode( ', ', $terms_names) . '<strong>';
}
}
// Outputing The html
echo $html.'</p>';
echo $attr_count .' | '.$count;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works…