Magento2: Multi website - customer create form - Attribute Cache not taking account the current website/store

Created on 21 Sep 2017  路  17Comments  路  Source: magento/magento2

Preconditions

  1. Magento CE 2.1.9
  2. Multi website / and multi stores (B2B (with languages : FR, EN) + B2C (with languages FR, EN, JP)
  3. Php 5.6

Steps to reproduce

  1. For the B2b website I want to display Tax / Vat field. And I don't want to display DOB field
  2. For the B2C website I don't want to display Tax / Vat field, but I do want to display DOB field (optional).
  3. So I set up these parameters in the backend Stores => Settings/Configuration => Customers / Customers configuration => Name and Address Options

| Website | Setting | Value |
| - | - | - |
| B2B | Show Date of birth | No
|B2B | Show Tax/VAT Number | Optional |
| B2C | Show Date of birth | Otptional |
| B2C | Show Tax/VAT Number | No |

Expected result

  1. I flush all cache
  2. I go to B2B website on customer/account/create => generate form and display Tax / Vat field as optional and hide Dob field
  3. I go to B2C website on customer/account/create => generate form and display Dob field as optional but hide Tax / Vat field.

Actual result

  1. I flush all cache
  2. I go to B2B website on customer/account/create => generate form and it display Tax / Vat field as optional and hide Dob field => OK!
  3. I go to B2C website on customer/account/create => generate form and it display the same form as B2B website => NOK!
  1. I flush cache
  2. I go to B2C website on customer/account/create => generate form and it display Dob field as optional but hide Tax / Vat field => OK!
  3. I go to B2B website on customer/account/create => gernerate form and it display the same form as B2C website => NOK!

going deeper in the code I think the problem is related to the AttributeCache class :

Magento\Customer\Block\Widget\Taxvat
Magento\Customer\Block\Widget\AbstractWidget::_getAttribute (:96)
Magento\Customer\Model\Metadata::getAttributeMetadata (:62)
Magento\Eav\Model\Entity\AttributeCache::saveAttributes (:108)
=> The cache Key does not take the website_id or store_id into account.
So once it is cached on a website it will give the same result on the other websites.

Eav Confirmed P2 ready for dev Reproduced on 2.2.x Reproduced on 2.3.x S2

Most helpful comment

I have got it the same issue. It's really a serious issue. Some of the customers not able to do the registration. I am strange to see that @m2-community-project added in low priority, How disgusting?
Disable the EAV cache is not a solution, it's a serious issue. Magento community must provide the solution for this. It's occurring in Enterprise and Cloud as well. Poor Magento community
@magento-engcom-team

All 17 comments

@eInyzant thanks for bug report!

Yeah, this mechanism was quite buggy and thus it was decided to completely eliminate it in 2.2.0: https://github.com/magento/magento2/commit/3ae7c1909daad96d5a0ad6ab7048455448ba7480

This is not something that could be backported due to BC constraints, as a workaround you can try just to disable this cache type.

In 2.2.2 the first website loaded, still caches the visibility and requirement for the attribute for all websites.

Magento\Customer\etc\di.xml (:38)

<preference for="Magento\Customer\Api\CustomerMetadataInterface"
                type="Magento\Customer\Model\Metadata\CustomerCachedMetadata" />

Seems to be the issue, the taxvat still gets cached in the customer metadata.

Hi @Hexmage, are you saying that the issue is still reproduced on 2.2.2 with exactly the same steps?

@orlangur yes. But I only specifically tested taxvat.

@orlangur And the issue is also present on the customer/account/edit page.

@Hexmage, thanks, reopening for recheck then.

@orlangur I believe the issue is caused by the fact that the taxvat settings are cached in the Customer Metadata.

@eInyzant, thank you for your report.
We've acknowledged the issue and added to our backlog.

Hi,

Just adding my 2 cents : I used the method descripted here which works perfectly for the per-website visibility on a customer attribute on the customer/register form.

BUT in 2.2.2 it seems to fails on a customer address attribute (say "telephone" - yes, it requires you to change in DB the "customer_eav_attribute/is_system" to 0 for that attribute to change the settings in admin) according to the page/form you hit first after a cache refresh.

TL;DR version : if you plan to use that method for a customer address attribute, double checks what happens after a cache flush when hitting FIRST on a customer/address/edit page THEN a customer/account/create page and vice versa.

Long version :
A bit of context : I tricked by layouting my customer/register form to show the customer address fields, so a customer which register even outside the checkout has to provide both contact info and a default address.
I changed the is_required of telephone : required for website/store A, not required for website/store B.
I also changed the Magento_CustomerCustomAttributes/templates/customer/form/edit and register.phtml to \Magento\Customer\Block\Widget\Telephone instead of an hard-coded required telephone field.

From a starting point with no cache whatsoever :

  • if I refresh first the customer/account/create pages on each website/store, it's ok : the 'telephone' customer address attribute is required when it should, not required when it should not

    • if I then go on a customer/address/edit in the customer account area, it's ok too : the 'telephone' attr. is required on A, not required on B

  • BUT if a customer/address/edit page is hit first on website A (where the attr. is required) after the cache clean, then 'telephone' becomes required on the customer/address/edit of website B too

    • of course, the customer/account/create form of B is also impacted

I've tried to dig, so far, I suspect something inside \Magento\Customer\Model\AttributeMetadataDataProvider and \Magento\Eav\Model\Config :

  • \Magento\Customer\Model\AttributeMetadataDataProvider::getAllAttributeCodes injects a store context before calling \Magento\Eav\Model\Config::getEntityAttributeCodes
  • \Magento\Customer\Model\AttributeMetadataDataProvider::getAttribute does not

\Magento\Eav\Model\Config::getEntityAttributes maintains cache objects which correctly vary according to the current store but also uses/updates a memory cache shared with \Magento\Customer\Model\AttributeMetadataDataProvider::getAttribute (see \Magento\Eav\Model\Config::loadAttributes and \Magento\Eav\Model\Config::saveAttribute and \Magento\Eav\Model\Config::_createAttribute).

The cache key used in \Magento\Eav\Model\Config::getEntityAttributes is built as

$cacheKey = self::ATTRIBUTES_CACHE_ID . '-' . $entityType->getId() . '-' . $storeId . '-' . $attributeSetId;

=> On the customer/account/create page, the code never reaches the last lines of \Magento\Eav\Model\Config::getEntityAttributes with an entity type of 2 (customer address attributes).

        $this->attributesPerSet[$cacheKey] = $attributes;

        return $attributes;
    }

The sequences of cacheKeys on that line for customer/account/create pages are :

3 [store_id] 3
3       0        0

On a customer/account/edit they are :

1 [store_id] 0
2      0         0
2      0         2
2 [store_id] 2
1 [store_id] 1
3 [store_id] 3
3      0         0

The first 3 entries are reached before the Telephone widget is executed (so before the getIsRequired() call).
From the look of the call stacks, it's related to the logged-in customer data retrieval (customer info + customer's addresses collection).

Will try to keep digging ...

Regards,
RB.

Any updates on this issue? This seems like a bug that breaks a lot of the purposes of a multi website enviroment

@magento-engcom-team Thank you for verifying the issue. Based on the provided information internal tickets MAGETWO-95133, MAGETWO-95134 were created

I have created a module for now that just retrieves the config like any user would expect. I do not see the advantage of loading the whole attribute from the cache to get those settings.

With the use of plugins i overwrite all the isRequired() and isVisible() methods

I also believe that getting the settings provide less load then getting the whole attribute even if it is from the cache

Hi @magento-engcom-team, is there any update on this being fixed? I am seeing this issue in a 2.2.6 build too.

Hello

TL;DR

I have encountered a similar phenomenon which i believe has the same root cause as this problem here.

For a better structure i am using the issue template.

Preconditions (*)

  1. Magento CE 2.3.4
  2. PHP 7.2
  3. Two stores (B2B and B2C) and for each own websites and view

Steps to reproduce (*)

  1. Go to backend configuration and switch scope to B2B store
  2. Set Customers->Customer Configuration->Create New Account Options->Show VAT Number on Storefront to yes (in config path: customer/create_account/vat_frontend_visibility)
  3. Set Customers->Customer Configuration->Name and Address Options->Show VAT Number on Storefront to required (in config path: customer/address/taxvat_show)
  4. Flush the cache
  5. Goto customer register account on storefront in B2B store
  6. Create a new account
  7. Go back to the backend and open the newly created customer
  8. Try to save the customer (it doesn麓t matter if a value gets changed)

Expected result (*)

  1. The account gets saved successfully

Actual result (*)

  1. Error stating that: The "Tax/VAT Number" attribute value is empty

You can solve the problem when you flush the eav ("EAV types and attributes") cache.

What i think happens internally: The attribute gets rendered in the form as required and therefore gets saved in the attribute cache as required. Then when you openen the customer in backend the attribute gets shown as optional (as the default settings state), but the attribute is cached as required. Because there is apperently no checking of the store or website within the cache the validation failed. What I can麓t explain is why the value is empty in the first place, because when you check the validation function in code the value is always empty.

My debugged call stack:
vendor/magento/module-customer/Controller/Adminhtml/Index/Validate.php:58
vendor/magento/module-customer/Model/AccountManagement.php:1057

Preconditions (*)
Magento CE 2.3.4
PHP 7.3
Two stores (B2B and B2C) - 1 Website / 1 Store View attached

Same issue, as soon as you open up one store, it caches the settings for that store and the other store has to have the same fields.

Edit: Disable eav cache and problem resolved.

I have got it the same issue. It's really a serious issue. Some of the customers not able to do the registration. I am strange to see that @m2-community-project added in low priority, How disgusting?
Disable the EAV cache is not a solution, it's a serious issue. Magento community must provide the solution for this. It's occurring in Enterprise and Cloud as well. Poor Magento community
@magento-engcom-team

This issue is reproduced in the Magento 2.3.5-p1.

Was this page helpful?
0 / 5 - 0 ratings