Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
It would appear the commerce_product_default_variation_alter()
hook is now dead, and \Drupal\commerce_product\Entity\Product->getDefaultVariation()
blindly returns the first active variation.
How should I go about altering this behaviour?
Comment | File | Size | Author |
---|---|---|---|
#33 | allow_altering_the_d-2835629-33.patch | 9 KB | mglaman |
| |||
#32 | allow_altering_the_d-2835629-32.patch | 4.38 KB | mglaman |
| |||
#18 | 2835629-13-rerolled.patch | 4.13 KB | a.dmitriiev |
| |||
#13 | 2835629-13.patch | 4.13 KB | flocondetoile |
| |||
#9 | default_variation_hook-2835629-9.patch | 4.13 KB | vasike |
Comments
Comment #2
bojanz CreditAttribution: bojanz at Centarro commentedNot possible, we always take the first one. So, retitling the issue.
What's your use case?
Comment #3
John Pitcairn CreditAttribution: John Pitcairn commentedThanks. It was possible in Commerce 1.x, via the hook mentioned.
Use case is that the client needs to display a different variation of a course product, depending on which industry sector the (anonymous) user has indicated they belong to earlier in their site visit.
Comment #4
agoradesign CreditAttribution: agoradesign commentedAnother use case would be to determine the default variation based on the attribute weights, rather than the variation's position in the product's entity reference field
Comment #5
John Pitcairn CreditAttribution: John Pitcairn commentedOr in the case of stocking systems, avoid displaying a default variation that is out of stock.
Comment #6
vasikei'll take a look
Comment #7
vasikethere is a patch for this.
Didn't use alter, but a hook
Comment #8
bojanz CreditAttribution: bojanz at Centarro commentedWe need an event, Commerce has no hooks.
Comment #9
vasikehere is a new patch using an Event
Comment #10
vasikeComment #11
jespermb CreditAttribution: jespermb at Adapt commentedWe have tried this patch on our current project and can confirm that it works. Nice work. :)
Comment #12
Hubbs CreditAttribution: Hubbs at Acro Commerce commentedThis patch now fails to apply so setting back to needs work.
Unfortunately, I'm not able to provide more details as to why. My knowledge of development is quite limited.
Comment #13
flocondetoilepatch #9 rerolled
Comment #14
Hubbs CreditAttribution: Hubbs at Acro Commerce commentedPatch applies now.
getDefaultVariation() does return the variation object.
I'm not able to use the setDefaultVariation() function. I tried setDefaultVariation() on a product entity but couldn't see any results when debugging the product entity. Error log shows:
Error: Call to undefined method Drupal\commerce_product\Entity\Product::setDefaultVariation().
Comment #15
Maico de Jong#9 worked for me! :)
Comment #16
batkorHi!
#13 worked for me! TY!
Will help someone
1. drush gen event-subscriber
2. Correct subscriber class
3. Create metod
myLogicalForGetDefaultVariation
Comment #17
kmajzlik CreditAttribution: kmajzlik as a volunteer commentedWorks nice for me.
Comment #18
a.dmitriiev CreditAttribution: a.dmitriiev as a volunteer and commentedPatch 13 works for me as well. Very elegant solution with EventSubscriber.
Usefull link for generating the subscriber with drupal console https://hechoendrupal.gitbooks.io/drupal-console/content/en/commands/gen...
But I had to reroll that patch so it is applied to current dev branch
Comment #19
arpad.rozsa CreditAttribution: arpad.rozsa at Studio Present commentedI can also say that, this works for me as well. Setting to RTBC since it's sitting here for a while now and would be nice to get it committed.
Comment #21
yonailo CreditAttribution: yonailo commentedYes this patch is very useful.
I am trying to understand how the view's button 'add_to_cart' is able to add the right product-variation to the cart. Reading the code inside ProductLazyBuilders there is a call to 'getDefaultVariation()' that always returns the first variation. I don't understand how and where views handles this.
Any help would be appreciated.
Comment #22
yonailo CreditAttribution: yonailo commentedIn fact, I have just realized that my view does not work, I always get the first variation even when I click on the add-to-cart button of the second variation.
Comment #23
motame CreditAttribution: motame commentedDoes someone propose an example where to place such code ? the two class methods proposed by batkor in the comment 16
I want to set the default price as the one of the variation with the lowest price.
Comment #24
a.dmitriiev CreditAttribution: a.dmitriiev as a volunteer and commented@motame you need in your module create EventSubscriber here: `your_module/src/EventSubscriber/YourEventSubscriber.php` with 2 methods from the comment #16 and also register that subscriber in your_module.services.yml file:
Or use instructions in comment #16 using drush to generate the subscriber automatically.
Don't forget to clean the caches afterwards.
Comment #25
motame CreditAttribution: motame commentedWith the service included in my_module.services.yml, it works and it is indeed a very elegant way to do it (using a service instead of a hook) !
Thank you very much a.dmitriiev.
Comment #26
kmajzlik CreditAttribution: kmajzlik as a volunteer commentedCommerce guys should look on it and merge. It is boring to still re-roll and check for patch changes on each composer update ...
Comment #27
agoradesign CreditAttribution: agoradesign commentedthere are no Commerce Guys anymore ;)))) you have to call for Centarro ;)
Comment #28
flocondetoileAlso, adding tests to this new feature should help a lot to get this patch committed.
Comment #29
dench0 CreditAttribution: dench0 commented@bojanz One of use case for this: is to show by default variation with available stock level. With current code - it almost impossible to do this and by default always showing first variation, even if it is out of the stock. But with #18 patch it possible to accomplish this with just dozen lines of code.
Comment #30
mglamanHm, taking a look. We could fire an event. However, we usually recommend using
\Drupal\commerce_product\ProductVariationStorage::loadFromContext
and\Drupal\commerce_product\ProductVariationStorage::loadEnabled
.Quickly looking over things:
ProductVariationStorageInterface::loadFromContext
gets the variation from the current query parameter, the fallback is to useProductInterface::getDefaultVariation
ProductInterface::getDefaultVariation
loops through all variations and returns the first entity that is published and accessibleProductVariationStorageInterface::loadEnabled
performs checks likeProductInterface::getDefaultVariation
- it loads all published and accessible variations. But it also firesProductEvents::FILTER_VARIATIONS
to limit the allowed variations.So we do have a possible problem where getDefaultVariation would allow a default variation that isn't available from
ProductVariationStorageInterface::loadEnabled
. That can be a separate issue to file, as it doesn't regard altering the default but instead what is available to select from the defaults.For example, filtering variations wouldn't fix #29 because you may want to still display it as an option, but not the default one.
I do, however, have to kick it to Needs Work because there are no tests covering the event.
Also: I wonder if there are any performance implications? We fire
getDefaultVariation
when rendering the add to cart form, and the product view builder. It is also invoked by \Drupal\commerce_product\ProductVariationStorage::loadFromContext which is called a few times. I wonder if we can use a static variable to prevent duplicated event dispatches. I can be a follow-up, as it's even an improvement to our current operations.So, to summarize next steps:
Comment #31
mglamanLinking to #3135918: Use a static cache in getDefaultVariation for performance. I'd definitely want some kind of protection from firing the event multiple times for a single order in one request.
Comment #32
mglamanHere's a rerolled patch now that #3135918: Use a static cache in getDefaultVariation for performance landed. I'll work on a test.
Comment #33
mglamanAnd here's a test.
Comment #34
jsacksick CreditAttribution: jsacksick at Centarro commentedPatch looks good to me! Tests are passing, we're probably just missing a @coversDefaultClass?
Comment #36
mglamanre:
@coversDefaultClass
we're not really testing that class specifically, but the integration of it.Giving authorship to vasike, since he wrote the first patch. Thanks, everyone else for the rerolls and feedback.
Committed! This will go out in the next release.
Comment #38
ConradFlashback CreditAttribution: ConradFlashback commentedI have a custom code similar to #16.
With my last Drupal 8 version everything works well.
I have updated now to D9.33 and PHP 8.1 but it doesn't show add to cart button for products that use $event->setDefaultVariation($defaultVariation);
But setDefaultVariation works well because custom logs show correct values.
No php error in log.
Any idea?
Comment #39
agoradesign CreditAttribution: agoradesign commentedmaybe the problem isn't caused by your event handler, but rather with the display -> there's this recent fix #3257191: PHP 8.1 "Error: Nesting level too deep" in ProductVariationWidgetBase.php with preselected variation that fixes an error with PHP 8.1
Comment #40
ConradFlashback CreditAttribution: ConradFlashback commented@agoradesign
Yes, this is the error!
Thanks! You save my day.
Comment #41
agoradesign CreditAttribution: agoradesign commentedyou're welcome :)