{"action":"opened","issue":{"url":"https://api.github.com/repos/magento/magento2/issues/15897","repository_url":"https://api.github.com/repos/magento/magento2","labels_url":"https://api.github.com/repos/magento/magento2/issues/15897/labels{/name}","comments_url":"https://api.github.com/repos/magento/magento2/issues/15897/comments","events_url":"https://api.github.com/repos/magento/magento2/issues/15897/events","html_url":"https://github.com/magento/magento2/issues/15897","id":329839029,"node_id":"MDU6SXNzdWUzMjk4MzkwMjk=","number":15897,"title":"Unable to save customer attribute. Missing attribute set id when save customer.","user":{"login":"hungpvdevsm","id":37575785,"node_id":"MDQ6VXNlcjM3NTc1Nzg1","avatar_url":"https://avatars1.githubusercontent.com/u/37575785?v=4","gravatar_id":"","url":"https://api.github.com/users/hungpvdevsm","html_url":"https://github.com/hungpvdevsm","followers_url":"https://api.github.com/users/hungpvdevsm/followers","following_url":"https://api.github.com/users/hungpvdevsm/following{/other_user}","gists_url":"https://api.github.com/users/hungpvdevsm/gists{/gist_id}","starred_url":"https://api.github.com/users/hungpvdevsm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hungpvdevsm/subscriptions","organizations_url":"https://api.github.com/users/hungpvdevsm/orgs","repos_url":"https://api.github.com/users/hungpvdevsm/repos","events_url":"https://api.github.com/users/hungpvdevsm/events{/privacy}","received_events_url":"https://api.github.com/users/hungpvdevsm/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-06-06T12:06:32Z","updated_at":"2018-06-06T12:06:32Z","closed_at":null,"author_association":"NONE","body":"Happen in Magento 2.2.x, tested in 2.2.0 & 2.2.4. \r\n2.1.x still works but still  have issue. After few hours debug to magento core i found the problem. \r\n\r\n**Step to procedure**\r\n1. Create custom attribute with setup script. \r\n```\r\n$eavSetup->addAttribute(\r\n                \\Magento\\Customer\\Model\\Customer::ENTITY,\r\n                'saved_tokens',\r\n                [\r\n                    'type'         => 'text',\r\n                    'input'        => 'hidden',\r\n                    'label'        => '',\r\n                    'required'     => 0,\r\n                    'user_defined' => 0,\r\n                    'visible'      => 0,\r\n                    'backend'      => '$path\\Token\\Backend',\r\n                ]\r\n            );\r\n```\r\nBackend file response for encrypt & decrypt  value.\r\n\r\n2. Update custom attribute value\r\nThis attribute was use for saving customer 's payment token, there are a lot of code for this so i won't post full code. Just simple set data to customer model in some controller.\r\n\r\n```\r\n$customer->setSavedTokens('some string');\r\n$customer->save();\r\n```\r\n### Expected result\r\nCustomer attribute should be saved.\r\n\r\n### Actual result\r\nCustomer attribute is not saved. \r\n\r\nAfter few hours digging in magento core. The main problem of this issue is customer entity does not have attribute set id value.\r\nPlease take a look at \\Magento\\Eav\\Model\\Entity\\AbstractEntity::_collectSaveData\r\nLine 1331, we have this:\r\n```\r\nif (!$attribute->isInSet($newObject->getAttributeSetId()) && !in_array($k, $staticFields)) {\r\n                $this->_aggregateDeleteData($delete, $attribute, $newObject);\r\n                continue;\r\n            }\r\n```\r\nIf attribute is not in same set with object & not in staticFields array. It will be deleted. \r\nBe cause of my attribute is custom attribute, !in_array($k, $staticFields) is true.\r\nSo we we will see isInSet function:\r\n ```\r\npublic function isInSet($setId)\r\n    {\r\n        if (!$this->hasAttributeSetInfo()) {\r\n            return true;\r\n        }\r\n\r\n        if (is_array($setId) && count(array_intersect($setId, array_keys($this->getAttributeSetInfo())))) {\r\n            return true;\r\n        }\r\n\r\n        if (!is_array($setId) && array_key_exists($setId, $this->getAttributeSetInfo())) {\r\n            return true;\r\n        }\r\n\r\n        return false;\r\n    }\r\n```\r\n\r\n**In 2.1**, !$this->hasAttributeSetInfo() is true. Well, it's bug as i know. Because attribute does have attribute set info. It belong to customer attribute set, which have attribute set id hard value = 1. Related issue [#4677](https://github.com/magento/magento2/issues/4677)\r\n\r\nLucky for us, we have return true inside if condition. It make my attribute value is not deleted. After that, everything work as expected. Attribute value is saved. \r\n\r\n**In 2.2**, $this->hasAttributeSetInfo() is not null anymore. It seem this bug is fixed.\r\n![image](https://user-images.githubusercontent.com/37575785/41036646-f21524e8-69ba-11e8-91dc-cdb3cf0104aa.png)\r\nContinue, we have $setId is null, so isInSet return false, it make my attribute value is deleted. Then  customer value are saved, except my attribute. \r\n\r\nNotes: \r\n$setId is null in both Magento 2.1 & 2.2. I'm consider this is bug. Because currently, customer entity does have attribute set id = 1. We can see const for that in \\Magento\\Customer\\Api\\CustomerMetadataInterface::ATTRIBUTE_SET_ID_CUSTOMER. \r\n\r\nWorkaround for this issue is pretty simple. Before save customer, we set attribute set id = const above. "}}
{"actor":{"display_login":"hungpvdevsm"}}