Drupal Commerce: Can't get variation type machine name from product variation object - drupal

I successfully receive product variation object by its id
$variation = \Drupal::entityTypeManager()->getStorage('commerce_product_variation')->load(8);
Then I successfully receive its structure like
(
[variation_id] => Array
(
[x-default] => 8
)
[type] => Array
(
[x-default] => router
)
[uuid] => Array
(
[x-default] => a44c2c31-2131-4c99-82a6-856b566d97cf
)
...
by print_r() like
echo '<pre>';
print_r($variation);
echo '</pre>';
Now if I try to get SKU through $variation->sku->value, I get it
But if I try to get variation type machine name through $variation->type->value I get nothing (and gettype($variation->type->value) returns NULL).
Still, we see it in the structure with the value router
Why and how to get the machine name ?

It's strange: the print_r() shows the way is $variation->type->value
But I've just successfully got it by
$variation->type[0]->target_id

This answer may be useful for someone who stumbles upon this post in the future
To get the machine name of the variation type from a product variation object in Drupal 9 Commerce, you can use the following code:
<?php
use Drupal\commerce\PurchasableEntityInterface;
// Load the product variation object.
$product_variation = ...;
// Ensure the object is a valid product variation.
if ($product_variation instanceof PurchasableEntityInterface) {
// Get the variation type.
$variation_type = $product_variation->getPurchasedEntity()->bundle();
// Get the variation type machine name.
$variation_type_machine_name = $variation_type->id();
// Use the variation type machine name as needed.
...
}
This code uses the PurchasableEntityInterface to ensure that the loaded object is a valid product variation. The getPurchasedEntity() method is used to get the underlying entity that represents the variation, and the bundle() method is used to get the variation type. The variation type machine name can then be obtained using the id() method.

Related

How can I count the instances of a custom taxonomy term in the scope of a custom post type?

I have a custom taxonomy called "tasks" shared between two custom post types of "roles" and "products".
Expected results:
I need to count how many times a given "task" term is used for each "role" post type minus the count shared by a "product" post type using the same "task" term.
Actual results:
None to report as I don't know how to tackle this
Error messages:
None
What I've tried:
Google keeps coming back with how to count the post type, not the terms :(
The code below is my plan B. Here I am just doing some micro loops on each post-type (only one shown below for brevity), getting the tasks and turning them into an associative array via array_count_values
$taskList = [];
$queryRoles = new WP_Query( array(
"post_type" => "roles"
));
while ( $queryRoles->have_posts() ) : $queryRoles->the_post();
$tasks = get_the_terms( get_the_ID(), "tasks" );
foreach ( $tasks as $task ) :
$taskList[] = $task->name;
endforeach;
endwhile;
$overlappingRoleTasks = $taskList;
print_r(array_count_values($taskList));
you could do a loop restricted to only posts with tasks assigned and one restricted to only products with assigned tasks.
Then using sizeof(); which return the number of elements in an array, count each number of posts and products and then do some basic php maths.
More about sizeof(); # https://www.w3schools.com/php/func_array_sizeof.asp

How to reliably retrieve product attribute data?

On a site where I started with WooCommerce version 2.. and then upgraded through newer releases (3.0.0, 3.0.1, ... 3.0.4), I'm noticing an inconsistency in how the order item meta data is stored for product attributes.
When using an attribute "Class Date" for variations, when an order is placed for some products in the store, the meta data for Class Date is stored using the key "pa_class-date". But for other products, the data for that same attribute is stored using the key "class-date".
My code for fetching attribute data looks like this:
$items = $order->get_items();
if ( isset($item['item_meta']['class-date']) ) {
$class_date = $item['item_meta']['class-date'];
} elseif ( isset($item['item_meta']['pa_class-date']) ) {
$class_date = $item['item_meta']['pa_class-date'];
} else {
error_log("Missing class date. We tried pa_class-date and class-date, but both are empty");
}
I would like to be able to simplify this to just look in one key or the other (pa_class-date or class-date, not both). Is that possible?
Here is what a dump of the order meta data looks like for the purchase of two different products. This one uses pa_class-date.
[467] => stdClass Object
(
[key] => pa_class-date
[value] => 2017-09-01
[display_key] => Class Date
[display_value] => <p>2017-09-01</p>
)
But for a different product, the data stored using the key "class-date":
26-Apr-2017 16:26:06 UTC] Array
(
[480] => stdClass Object
(
[key] => class-date
[value] => 2017-05-18
[display_key] => Class Date
[display_value] => <p>2017-05-18</p>
)
What causes the inconsistency in which key is used to store the data?
What is the most reliable (futureproof) way to retrieve the data?
This inconsistency is possible. But its inconsistent data entry rather. When you add attribute to Products >> Attributes, they become part of woocommerce system. Then you can map them to variation by just selecting on product details page.
However, when you add "Custom Attribute" directly from product details page, that data will be specific for that product and can cause inconsistency.

Alter views search api solr result

I am using search api and Solr, When I echo the result variable , it gave me the following results
stdClass Object
(
[entity] => 442415
[_entity_properties] => Array
(
[search_api_relevance] => 1
[search_api_excerpt] =>
[search_api_item_id] => 442415
)
)
In views i added ( custom text field, that is global variable), With this nid 442415, i will do certain node load operation and finally,
i will get price for the specific product. This code block will execute inside the foreach.
_views_pre_render
Please guideme,
which hook i should use , _views_post_execute or _views_pre_render ?
How to assign new value in to which variable and how to print that in tpl
Finally, i want to display the price on each item
This link resolved my problem.
Solution approach
function mymodule_views_pre_render(&$view) {
if($view->name == 'my_view') {
foreach($view->result as &$row) {
$row->_entity_properties['nothing'] = 'new value';
}
}
}
views-view-field--view-name--display-name--nothing.tpl.php
print $row->_entity_properties['nothing'];

Get all product variations of a product given its ID in Woocommerce

I have a custom page where I'm trying to list every products in the store along with their variations.
Also, I'm trying to list the variations' prices sorted by the product attribute with slug 'size'
For testing, I'm trying to get the variations of a single product with the ID 381
My code yet is
$handle=new WC_Product('381');
$variations1=$handle->get_avaialable_variations();
foreach ($variations1 as $key => $value) {
echo '<option value="'.$value['variation_id'].'">'.implode('/',$value['attributes']).'-'.$value['price_html'].'</option>';
}
But the error I'm getting is
PHP Fatal error: Call to undefined method WC_Product::get_avaialable_variations()
I tried using
$handle=new WC_Product_Variable('381');
instead of
$handle=new WC_Product('381');
But the error is the same.
Any help here?
Try this code.
$handle=new WC_Product_Variable('12');
$variations1=$handle->get_children();
foreach ($variations1 as $value) {
$single_variation=new WC_Product_Variation($value);
echo '<option value="'.$value.'">'.implode(" / ", $single_variation->get_variation_attributes()).'-'.get_woocommerce_currency_symbol().$single_variation->price.'</option>';
}
Note: Use this $single_variation->get_price_html() but its outputs with html span tag which results in getting hidden in option tags.
Tested the above code and the results are as follows.
Let me know if that worked for you too.
You had a typo in your code - get_avaialable_variations
It should be get_available_variations
function get_variation_data_from_variation_id($item_id) {
$_product = new WC_Product_Variation($item_id);
$variation_data = $_product->get_variation_attributes(); // variation data in array
$variation_detail = woocommerce_get_formatted_variation($variation_data, true); // this will give all variation detail in one line
// $variation_detail = woocommerce_get_formatted_variation( $variation_data, false); // this will give all variation detail one by one
return $variation_data; // $variation_detail will return string containing variation detail which can be used to print on website
// return $variation_data; // $variation_data will return only the data which can be used to store variation data
}
I found this before on stackoverflow couldn't remember the link (please edit if find the link to the answer with this method). it shows the variation data for output. the method takes variation id as perameter.
output:
.

Can't get shipping methods from order in woocommerce extension but can in theme

I'm developing a woocommerce extension and have the following section of code in one of my classes.
$order = new WC_Order(159);
$shipping_methods = $order->get_shipping_methods();
print_r($shipping_methods);
This is returning an empty array as seen here.
[24-Sep-2014 04:05:02 UTC] Array
(
)
If I place the exact same piece of code in my theme instead the array is populated as expected and returns the following
Array
(
[10] => Array
(
[name] => International Delivery
[type] => shipping
[item_meta] => Array
(
[method_id] => Array
(
[0] => international_delivery
)
[cost] => Array
(
[0] => 175
)
)
[method_id] => international_delivery
[cost] => 175
)
)
I've tried debugging this but cannot for the life of me work out what I've missed. The same three lines of code work in the theme, but don't work in the plugin. Is there a global or other variable I've missed?
EDIT:
The order object I am creating is already a completed order and I am just querying the information from it. I'm not sure if this is a loading issue as suggested below.
Also when I var_dump $order it is showing me the order object. Is there any reason why the inherited methods from the WC_Abstract_Order would not work at this point?
WP_DEBUG is on and no errors or warnings are being produced.
Also to note, this is in a class that extends WC_Email.
EDIT 2:
I have tracked down where the $order object gets messed with in my trigger method for WC_Email.
Calling this filter woocommerce_order_get_items breaks the $order object.
add_filter( 'woocommerce_order_get_items', array( $this, 'check_items' ), 10, 2 );
This is my line of code that if I disable this, then I am able to get access to the get_shipping_methods().
Do you have WP_DEBUG mode enabled? If so, I'd expect to see some fatal errors such as get_shipping_methods() does not exist or maybe "Call to a member function on a non-object", which would both leave $order undefined and thus empty when you var_dump it.
Plugins load before themes (see the Action Hooks Reference ), so WooCommerce is fully loaded by the time your theme is called. It is possible that your plugin is running before WooCommerce is loaded.
I would try running your code on a later hook, such as plugins_loaded or the WooCommerce-specific, woocommerce_loaded.
It turns out that the previous developer was iterating over the $items and unsetting lines items incorrectly. After much frustration I fixed the detection of the line_item vs shipping item and now the code is working.
This was then being passed on to all the filters for the $order object effectively removing all traces of the shipping information. Always check the code line for line. I did work out that 2 filters to change line items keep the object persistently across calls, which is why it was deleting the shipping info.

Resources