Woocommerce: Retrieve SKU of Variable Product Options - php

In Woocommerce, there is a block of code in variable.php that displays the variation options. I am needing to display the SKU of each individual variation in the list next to the title. Is there a way I can do this that is similar to $product->get_sku;?
This is the full block:
global $product;
$attribute_keys = array_keys( $attributes );
<?php foreach ( $attributes as $name => $options ) : ?>
<tr class="attribute-<?php echo sanitize_title($name); ?>">
<?php
$sanitized_name = sanitize_title( $name );
if ( isset( $_REQUEST[ 'attribute_' . $sanitized_name ] ) ) {
$checked_value = $_REQUEST[ 'attribute_' . $sanitized_name ];
} elseif ( isset( $selected_attributes[ $sanitized_name ] ) ) {
$checked_value = $selected_attributes[ $sanitized_name ];
} else {
$checked_value = '';
}
?>
<td class="value">
<?php
if ( ! empty( $options ) ) {
if ( taxonomy_exists( $name ) ) {
// Get terms if this is a taxonomy - ordered. We need the names too.
$terms = wc_get_product_terms( $product->get_id(), $name, array( 'fields' => 'all' ) );
foreach ( $terms as $term ) {
if ( ! in_array( $term->slug, $options ) ) {
continue;
}
print_attribute_radio( $checked_value, $term->slug, $term->name, $sanitized_name );
}
} else {
foreach ( $options as $option ) {
echo $product->get_sku; // This is where the variation SKU would go
print_attribute_radio( $checked_value, $option, $option, $sanitized_name );
}
}
}
echo end( $attribute_keys ) === $name ? apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . __( 'Clear', 'woocommerce' ) . '</a>' ) : '';
?>
</td>
</tr>
<?php endforeach; ?>
This is where the Variation SKU would go within this section:
foreach ( $options as $option ) {
echo $product->get_sku; // This is where the variation SKU would go
print_attribute_radio( $checked_value, $option, $option,
$sanitized_name );
}
Thanks.

Replace your foreach with:
$product = new WC_Product_Variable( $post->ID );
$variations = $product->get_available_variations();
foreach ($variations as $key => $variation) {
$sku = $variation['sku'];
$options = $variation['attributes'];
.
.
.

Related

Display price in variation WooCommerce not working with space in variation name

I use a function to add the price to the variation in the variation-dropdown in woocommerce. The problem is, when the variation name contains a space like "20 kg" the price is not showing. When i there is no space like "200kg" its working. What could be the problem?
function display_price_in_variation_options( $term ) {
$product = wc_get_product();
$id = $product->get_id();
if ( empty( $term ) || empty( $id ) ) {
return $term;
}
if ( $product->is_type( 'variable' ) ) {
$product_variations = $product->get_available_variations();
} else {
return $term;
}
foreach ( $product_variations as $variation ) {
if ( count( $variation['attributes'] ) > 1 ) {
return $term;
}
$attribute = array_values( $variation['attributes'] )[0];
if ( $attribute === $term ) {
$term .= ' (' . wp_strip_all_tags( wc_price( $variation['display_price'] ) ) . ')';
}
}
return $term;
}
add_filter( 'woocommerce_variation_option_name', 'display_price_in_variation_options' );
Variable $term returns a name of the attribute, whereas variable $attribute returns a slug. This is what caused a problem when you are trying to compare those 2 variables within IF statement.
You can pass additional parameter $term_obj to your function, which returns an object of the term.
Then you can get an actual slug of the term:
$term_obj->slug
And finally utilize it inside if statement: if ( $attribute === $term_obj->slug )
Revised function would look like:
function display_price_in_variation_options( $term, $term_obj ) {
$product = wc_get_product();
$id = $product->get_id();
if ( empty( $term ) || empty( $id ) ) {
return $term;
}
if ( $product->is_type( 'variable' ) ) {
$product_variations = $product->get_available_variations();
} else {
return $term;
}
foreach ( $product_variations as $variation ) {
if ( count( $variation['attributes'] ) > 1 ) {
return $term;
}
$attribute = array_values( $variation['attributes'] )[0];
if ( $attribute === $term_obj->slug ) {
$term .= ' (' . wp_strip_all_tags( wc_price( $variation['display_price'] ) ) . ')';
}
}
return $term;
}
add_filter( 'woocommerce_variation_option_name', 'display_price_in_variation_options', 10, 2 );
Update your code
function display_price_in_variation_options( $term ) {
$product = wc_get_product();
$id = $product->get_id();
if ( empty( $term ) || empty( $id ) ) {
return $term;
}
if ( $product->is_type( 'variable' ) ) {
$product_variations = $product->get_available_variations();
} else {
return $term;
}
foreach ( $product_variations as $variation ) {
if ( count( $variation['attributes'] ) > 1 ) {
return $term;
}
$attribute = str_replace(' ', '', $array_values( $variation['attributes'] )[0]);
if ( $attribute === $term ) {
$term .= ' (' . wp_strip_all_tags( wc_price( $variation['display_price'] ) ) . ')';
}
}
return $term;
}
add_filter( 'woocommerce_variation_option_name', 'display_price_in_variation_options' );

Woocommerce print simple product attributes on cart and checkout, like variable attributes

I want to show attibutes from a simple product, in cart and checkout. Just like variable products does, but there is only one attibute. See image below:
Is this possible to achive with PHP?
I was thinking about something like using echo $product->get_attributes()
Add the follows code snippets to achieve your above task -
function modify_woocommerce_get_item_data( $item_data, $cart_item ) {
if( $item_data || $cart_item['data']->is_type( 'variation' ) ) return $item_data;
if ( $cart_item['data']->is_type( 'simple' ) ) {
$attributes = array_filter( $cart_item['data']->get_attributes(), 'wc_attributes_array_filter_visible' );
foreach ( $attributes as $attribute ) {
$values = array();
if ( $attribute->is_taxonomy() ) {
$attribute_taxonomy = $attribute->get_taxonomy_object();
$attribute_values = wc_get_product_terms( $cart_item['data']->get_id(), $attribute->get_name(), array( 'fields' => 'all' ) );
foreach ( $attribute_values as $attribute_value ) {
$value_name = esc_html( $attribute_value->name );
if ( $attribute_taxonomy->attribute_public ) {
$values[] = '' . $value_name . '';
} else {
$values[] = $value_name;
}
}
} else {
$values = $attribute->get_options();
foreach ( $values as &$value ) {
$value = make_clickable( esc_html( $value ) );
}
}
$item_data[] = array(
'key' => wc_attribute_label( $attribute->get_name() ),
'value' => apply_filters( 'woocommerce_attribute', wpautop( wptexturize( implode( ', ', $values ) ) ), $attribute, $values ),
);
}
}
return $item_data;
}
add_filter( 'woocommerce_get_item_data', 'modify_woocommerce_get_item_data', 99, 2 );
Codes goes to your active theme's functions.php
Yes you can. Please try adding a filter as bellow,
add_filter('woocommerce_cart_item_name', function($name, $cart_item) {
//has attributes
if ($cart_item['data']->is_type( 'simple' ) && $attributes = $cart_item['data']->get_attributes()) {
$name .= " - ";
foreach ($attributes as $att)
$name .= $att->get_name() . " : " . implode(',', $att->get_options());
}
return $name;
}, 10, 2);

Add the variation price to variable product dropdown item names in Woocommerce

I'm using this code to get the variable product options
$terms = wc_get_product_terms( $bundle_product_id, $name, array( 'fields' => 'all' ) );
foreach ( $terms as $term ) {
if ( !in_array( $term->slug, $options ) ) {
continue;
}
echo '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $selected_value ), sanitize_title( $term->slug ), false ) . '>' . apply_filters( 'woocommerce_variation_option_name', $term->name ) . '</option>';
}
It will only work if you have just one product attribute for variations set in the variable product (so only one dropdown).
If you have more than one dropdowns in your variable product, as the variations are a combination of the different product attributes values, it will not work logically.
So the following code will display the product variation price in a unique product attribute dropdown:
// Utility function to get the price of a variation from it's attribute value
function get_the_variation_price_html( $product, $name, $term_slug ){
foreach ( $product->get_available_variations() as $variation ){
if($variation['attributes'][$name] == $term_slug ){
return strip_tags( $variation['price_html'] );
}
}
}
// Add the price to the dropdown options items.
add_filter( 'woocommerce_dropdown_variation_attribute_options_html', 'show_price_in_attribute_dropdown', 10, 2);
function show_price_in_attribute_dropdown( $html, $args ) {
// Only if there is a unique variation attribute (one dropdown)
if( sizeof($args['product']->get_variation_attributes()) == 1 ) :
$options = $args['options'];
$product = $args['product'];
$attribute = $args['attribute'];
$name = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
$id = $args['id'] ? $args['id'] : sanitize_title( $attribute );
$class = $args['class'];
$show_option_none = $args['show_option_none'] ? true : false;
$show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __( 'Choose an option', 'woocommerce' );
if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
$attributes = $product->get_variation_attributes();
$options = $attributes[ $attribute ];
}
$html = '<select id="' . esc_attr( $id ) . '" class="' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '" data-show_option_none="' . ( $show_option_none ? 'yes' : 'no' ) . '">';
$html .= '<option value="">' . esc_html( $show_option_none_text ) . '</option>';
if ( ! empty( $options ) ) {
if ( $product && taxonomy_exists( $attribute ) ) {
$terms = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) );
foreach ( $terms as $term ) {
if ( in_array( $term->slug, $options ) ) {
// Get and inserting the price
$price_html = get_the_variation_price_html( $product, $name, $term->slug );
$html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) . ' ::: ' . $price_html ) . '</option>';
}
}
} else {
foreach ( $options as $option ) {
$selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
// Get and inserting the price
$price_html = get_the_variation_price_html( $product, $name, $term->slug );
$html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) . ' ::: ' . $price_html ) . '</option>';
}
}
}
$html .= '</select>';
endif;
return $html;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Here is my simplified solution to this that is working with WooCommerce 4.7.0. Since we know there is only one attribute for each variation, we can just get the first value to show the correct price for each.
/**
* Display price in variation options dropdown for products that have only one attribute.
*
* #param string $term Existing option term value.
* #return string $term Existing option term value or updated term value with price.
*/
function display_price_in_variation_options( $term ) {
$product = wc_get_product();
$id = $product->get_id();
if ( empty( $term ) || empty( $id ) ) {
return $term;
}
if ( $product->is_type( 'variable' ) ) {
$product_variations = $product->get_available_variations();
} else {
return $term;
}
foreach ( $product_variations as $variation ) {
if ( count( $variation['attributes'] ) > 1 ) {
return $term;
}
$attribute = array_values( $variation['attributes'] )[0];
if ( $attribute === $term ) {
$term .= ' (' . wp_strip_all_tags( wc_price( $variation['display_price'] ) ) . ')';
}
}
return $term;
}
add_filter( 'woocommerce_variation_option_name', 'display_price_in_variation_options' );

List product variations using wc_dropdown_variation_attribute_options in Woocommerce

I am new to woocommerce and i am trying to display the product variations as a drop-down list in shop page. But the variations are not getting populated in the select option list. below is my code snippet.
<?php foreach ( $product->get_attributes() as $attribute_name => $options ) : ?>
<tr>
<td class="label"><label for="<?php echo sanitize_title( $attribute_name ); ?>"><?php echo wc_attribute_label( $attribute_name ); ?></label></td>
<td class="value">
<?php
//$selected = isset( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ? wc_clean( urldecode( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ) : $product->get_variation_default_attribute( $attribute_name );
//wc_dropdown_variation_attribute_options( array( 'options' => $options, 'attribute' => $attribute_name, 'product' => $product, 'selected' => $selected ) );
$args=array();
$result = wc_dropdown_variation_attribute_options($args);
echo end( $attribute_keys ) === $attribute_name ? apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . __( 'Clear', 'woocommerce' ) . '</a>' ) : '';
?>
</td>
</tr>
<?php endforeach;?>
The code that you have there comes from single-product/add-to-cart/variable.php template.
But you can't use it with $product->get_attributes() in the foreach loop.
In this template, $attributes is $product->get_variation_attributes()…
So the following code will work to display the attributes dropdowns (where $product is an instance of the variable product object):
<?php
$attributes = $product->get_variation_attributes();
$attribute_keys = array_keys( $attributes );
?>
<?php foreach ( $attributes as $attribute_name => $options ) : ?>
<tr>
<td class="label"><label for="<?php echo sanitize_title( $attribute_name ); ?>"><?php echo wc_attribute_label( $attribute_name ); ?></label></td>
<td class="value">
<?php
$selected = isset( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ? wc_clean( urldecode( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ) : $product->get_variation_default_attribute( $attribute_name );
$args = array( 'options' => $options, 'attribute' => $attribute_name, 'product' => $product, 'selected' => $selected );
wc_dropdown_variation_attribute_options( $args );
echo end( $attribute_keys ) === $attribute_name ? apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . __( 'Clear', 'woocommerce' ) . '</a>' ) : '';
?>
</td>
</tr>
<?php endforeach; ?>
As you can see the wc_dropdown_variation_attribute_options() function is made to display variation attribute dropdowns for the current variable product, BUT NOT a list of variations in a drop down.
List in a dropdown the product variations of a variable product:
To list all variation attributes in a dropdown you will use the following code (where $product is an instance of the variable product object):
$available_variations = $product->get_available_variations();
if( count($available_variations) > 0 ){
$output = '<div class="product-variations-dropdown">
<select id="available-variations" class="" name="available_variations">';
$output .= '<option value="">'. __('Choose a variation') .'</option>';
foreach( $available_variations as $variation ){
$option_value = array();
foreach( $variation['attributes'] as $attribute => $term_slug ){
$taxonomy = str_replace( 'attribute_', '', $attribute );
$attribute_name = get_taxonomy( $taxonomy )->labels->singular_name; // Attribute name
$term_name = get_term_by( 'slug', $term_slug, $taxonomy )->name; // Attribute value term name
$option_value[] = $attribute_name . ': '.$term_name;
}
$option_value = implode( ' | ', $option_value );
$output .= '<option value="'.$variation['variation_id'].'">'.$option_value.'</option>';
}
$output .= '
</select>
</div>';
echo $output;
}
Code is tested and works
To get an instance of the variable product object from a defined $product_id (where $product_id is the ID of a variable product) you will use:
$product = wc_get_product($product_id);

Woocommerce - Display more attributes on the cart

I have Woocommerce and Woocommerce Bookings. I want to add some more info on the cart, after a user added it there.
At the moment, I have the starting date of the booking and the duration, with a label.
<dl class="variation">
<dt class="variation-Booking"><font><font class="">Booking Date:</font></font></dt>
<dd class="variation-Booking"><p><font><font class="">August 11, 2015</font></font></p></dd>
<dt class="variation-Duration"><font><font>Duration:</font></font></dt>
<dd class="variation-Duration"><p><font><font>4 days</font></font></p></dd>
</dl>
I try to find where this code is created on the PHP files of Woocommerce, so I can either add more attributes that are available on the database (like ending date and SKU for example) and also change the HTML output.
In the cart.php file, there is this part of the code:
// Meta data
echo WC()->cart->get_item_data( $cart_item );
Then on class-wc-cart.php the above function:
public function get_item_data( $cart_item, $flat = false ) {
$item_data = array();
// Variation data
if ( ! empty( $cart_item['data']->variation_id ) && is_array( $cart_item['variation'] ) ) {
foreach ( $cart_item['variation'] as $name => $value ) {
if ( '' === $value )
continue;
$taxonomy = wc_attribute_taxonomy_name( str_replace( 'attribute_pa_', '', urldecode( $name ) ) );
// If this is a term slug, get the term's nice name
if ( taxonomy_exists( $taxonomy ) ) {
$term = get_term_by( 'slug', $value, $taxonomy );
if ( ! is_wp_error( $term ) && $term && $term->name ) {
$value = $term->name;
}
$label = wc_attribute_label( $taxonomy );
// If this is a custom option slug, get the options name
} else {
$value = apply_filters( 'woocommerce_variation_option_name', $value );
$product_attributes = $cart_item['data']->get_attributes();
if ( isset( $product_attributes[ str_replace( 'attribute_', '', $name ) ] ) ) {
$label = wc_attribute_label( $product_attributes[ str_replace( 'attribute_', '', $name ) ]['name'] );
} else {
$label = $name;
}
}
$item_data[] = array(
'key' => $label,
'value' => $value
);
}
}
// Other data - returned as array with name/value values
$other_data = apply_filters( 'woocommerce_get_item_data', array(), $cart_item );
if ( $other_data && is_array( $other_data ) && sizeof( $other_data ) > 0 ) {
foreach ( $other_data as $data ) {
// Set hidden to true to not display meta on cart.
if ( empty( $data['hidden'] ) ) {
$display_value = ! empty( $data['display'] ) ? $data['display'] : $data['value'];
$item_data[] = array(
'key' => $data['name'],
'value' => $display_value
);
}
}
}
// Output flat or in list format
if ( sizeof( $item_data ) > 0 ) {
ob_start();
if ( $flat ) {
foreach ( $item_data as $data ) {
echo esc_html( $data['key'] ) . ': ' . wp_kses_post( $data['value'] ) . "\n";
}
} else {
wc_get_template( 'cart/cart-item-data.php', array( 'item_data' => $item_data ) );
}
return ob_get_clean();
}
return '';
}
And the cart-item-data.php that is called above:
<dl class="variation">
<?php
foreach ( $item_data as $data ) :
$key = sanitize_text_field( $data['key'] );
?>
<dt class="variation-<?php echo sanitize_html_class( $key ); ?>"><?php echo wp_kses_post( $data['key'] ); ?>:</dt>
<dd class="variation-<?php echo sanitize_html_class( $key ); ?>"><?php echo wp_kses_post( wpautop( $data['value'] ) ); ?></dd>
<?php endforeach; ?>
</dl>
However, I am still unaware of how I can change the layout and add specific attributes from the database.
add_filter( 'woocommerce_get_item_data', 'wc_add_address_to_cart', 10, 2 );
function wc_add_address_to_cart( $other_data, $cart_item ) {
$post_data = get_post( $cart_item['product_id'] );
$post_data->post_author;
$vendor_id = $post_data->post_author;
echo '<br>';
$Add = 'Address: ';
$city = 'City: ';
$tel = 'Phone: ';
echo $test;
$user_id = $vendor_id;
// Get all user meta data for $user_id
$meta = get_user_meta( $user_id );
// Filter out empty meta data
$meta = array_filter( array_map( function( $a ) {
return $a[0];
}, $meta ) );
echo $Add;
print_r( $meta ['_vendor_address_1'] );
echo '<br>';
echo $city;
print_r( $meta['_vendor_city'] );
echo '<br>';
echo $tel;
print_r( $meta['_vendor_phone'] );
return $other_data;
}
Add this to the functions.php file in your theme. it will display the Address of each vendor on the products. you can customize it to what ever you want.

Categories