Description
Summary
Updating product url_key
via REST API ; Product Url Rewrites are not re-generated. (yeah, i know, thats crazy)
This occurs on actually "Simple" setup, out of the box : Single-store mode and calls on "all" Rest Endpoint {{magento_url}}/rest/all/V1/products/{{sku}}
, elementary school level
I use the term "Url Rewrites" (with a "s") because that involves category-path-product-urls also. But i focus on product "direct" url
Preconditions
- Magento CE 2.3.4 - Single store mode
- Magento 2.4-develop
- Calls made on "all" :
PUT
{{magento_url}}/rest/all/V1/products/{{sku}}
⚠️ Note: 2.4-develop doesn't containPOST
call for{{magento_url}}/rest/all/V1/products/{{sku}}
- Stores->Configuration->General->Single-Store Mode->Enable Single-Store Mode=Yes
Steps to reproduce
- Given a standard product (simple product, dont try to overcomplicate things)
- Said product has id=10 :
entity_id=10
- Current
url_key="my-product-url"
(In Admin Product View : Section "Search Engine Optimization")
- Said product has id=10 :
- Check current Url_Rewrites in (Marketing / SEO & Search / Url Rewrites)
- Search for target_path like
catalog/product/view/id/10
- Current url_rewrite should exist :
"my-product-url.html"
(i suppose ".html" as most used case prefix)
- Search for target_path like
- REST PUT Update on product :
Sorry, no time to write a one line curl call. If you read this, you're smart enough to use Postman and already have this call ready to go.PUT
{{magento_url}}/rest/all/V1/products/{{sku}}- Json pload :
{
"product": {
"custom_attributes": [
{
"attribute_code": "url_key",
"value": "my-new-url"
}
]
}
}
- Check Url_key has been updated (In Admin Product View : Section "Search Engine Optimization")
- Url_key is
my-new-url
(whaou)
- Url_key is
- Check Url_Rewrites in (Marketing / SEO & Search / Url Rewrites)
- Search for target_path like
catalog/product/view/id/10
(or update tab/search, as you want, take your time) - URL rewrites not updated
- Search for target_path like
Expected result
- URL Rewrites should have been updated
Actual result
- URL Rewrites NOT updated
Additional info
- There is absolutely NOTHING related to async, indexing, cache... No, thats really crazy : follow....
- Url rewrites ARE generated on product CREATION, but NOT ON UPDATE
- Passing websites_id on extension_attributes does not help (wait, it should, but wait...)
- Calling update on "default" rest endpoint instead of "all" would work BUT : IT IS A REALLY BAD IDEA :
You will not see "real value" for the store (1) in Admin product view (and NO way to see it in Single store mode)
There is another BUG that leads to almost ALL attributes to be copied for store 1 scope, not JUST the one you updated and, sorry but that sucks. I will ckeck if issue is already reported and eventually post. But poor chance to get a fix on that.
Debugging
Actually deep debugged code and i think the issue is on Product Model getStoreIds() even if it HARD to admit on such a central class :
Line $websiteIds = array_keys($websiteIds);
gets array_keys()... ???
Does not have much sense... : Website_ids being either an array from json OR retreived from DB : NO WAY that array_keys would be some website_ids !
Checked current 2.4 develop, still there : https://github.com/magento/magento2/blob/2.4-develop/app/code/Magento/Catalog/Model/Product.php#L832
Workaround / I would say "Hack"
To congratulate you for your patience reading me, i offer you this hack if you promise to have a good laugh :
The FACT is that the array_keys() "bug" CAN be used as a temporary workaround hack :
You can pass values so that there will be a key for the targeted website id.
If you pass twice (here) the website_id in extension attribute, you'll exploit the bug and pass => Will work.
Hopefully, these arrays are not "cleaned" by any interceptor before being in product data object... Not surprising.
I think you got what you have to do if you want to re-gen website id 4... LOL
{
"product": {
"custom_attributes": [
{
"attribute_code": "url_key",
"value": "my-url-key-16"
}
],
"extension_attributes": {
"website_ids": [
1,1
]
}
}
}
Exract from Magento\Catalog\Model\Product.php
...
public function getStoreIds()
{
if (!$this->hasStoreIds()) {
$storeIds = [];
if ($websiteIds = $this->getWebsiteIds()) {
if (!$this->isObjectNew() && $this->_storeManager->isSingleStoreMode()) {
$websiteIds = array_keys($websiteIds);
}
foreach ($websiteIds as $websiteId) {
$websiteStores = $this->_storeManager->getWebsite($websiteId)->getStoreIds();
$storeIds[] = $websiteStores;
}
}
if ($storeIds) {
$storeIds = array_merge(...$storeIds);
}
$this->setStoreIds($storeIds);
}
return $this->getData('store_ids');
}
...
Metadata
Metadata
Assignees
Labels
Type
Projects
Status