7

I am creating Product in magento usign Rest API. Using the below format:

{
"product": {
"name": "Product Name",
"sku": "product_name_1498227094",
"attribute_set_id": "18",
"status": 1,
"visibility": 4,
"type_id": "simple",
"price": 0,
"weight": 0,
"product_links": [],
"options": [],
"tier_prices": [],
"custom_attributes": [
 {
 "attribute_code": "description",
 "value": "Product About content"
 },
 {
 "attribute_code": "short_description",
 "value": "Product Mini content"
 },
 {
 "attribute_code": "meta_title",
 "value": "Product Name"
 },
 {
 "attribute_code": "meta_keyword",
 "value": "Product Name"
 },
 {
 "attribute_code": "meta_description",
 "value": "Product Name"
 }
]
},
"saveOptions": true
}

Its creating Product first time. But If I use the same data to create product again. I am getting the below error:

[message] => URL key for specified store already exists.

As you can check, I am not passing url_key in custom_attributes array.

{
 "attribute_code": "url_key",
 "value": "10090-white-xl"
}

Here my question is: Do magento2 not create Unique URL key automatically? How can we generate Unique URL key in magento2 with consideration of SEO also ?

asked Jun 23, 2017 at 14:41

5 Answers 5

14

I have created a custom code to check if the URL key exists or not. As per the flow used in product import functionality in Magento 2.

public function __construct(
 --
 \Magento\Store\Model\StoreManagerInterface $storeManager, 
 \Magento\Framework\App\ResourceConnection $resource, 
 --
) {
 --
 $this->_storeManager = $storeManager;
 $this->_resource = $resource;
 -- 
}
public function createUrlKey($title, $sku) 
{
 $url = preg_replace('#[^0-9a-z]+#i', '-', $title);
 $urlKey = strtolower($url);
 $storeId = (int) $this->_storeManager->getStore()->getStoreId();
 
 $isUnique = $this->checkUrlKeyDuplicates($sku, $urlKey, $storeId);
 if ($isUnique) {
 return $urlKey;
 } else {
 return $urlKey . '-' . time();
 }
}
/*
 * Function to check URL Key Duplicates in Database
 */
private function checkUrlKeyDuplicates($sku, $urlKey, $storeId) 
{
 $urlKey .= '.html';
 $connection = $this->_resource->getConnection(\Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION);
 $tablename = $connection->getTableName('url_rewrite');
 $sql = $connection->select()->from(
 ['url_rewrite' => $connection->getTableName('url_rewrite')], ['request_path', 'store_id']
 )->joinLeft(
 ['cpe' => $connection->getTableName('catalog_product_entity')], "cpe.entity_id = url_rewrite.entity_id"
 )->where('request_path IN (?)', $urlKey)
 ->where('store_id IN (?)', $storeId)
 ->where('cpe.sku not in (?)', $sku);
 $urlKeyDuplicates = $connection->fetchAssoc($sql);
 if (!empty($urlKeyDuplicates)) {
 return false;
 } else {
 return true;
 }
}
Chirag Prajapati
2,9522 gold badges20 silver badges44 bronze badges
answered Jul 4, 2017 at 6:56
1
  • In which file have you added this code? and which file have you overrided? Commented Feb 9, 2021 at 7:14
4

To perform the CreateUrlKey function, I added at the second line this code:

$lastCharTitle = substr($title, -1);
$lastUrlChar = substr($url, -1);
if ($lastUrlChar == "-" && $lastCharTitle != "-"){
 $url = substr($url, 0, strlen($url) - 1);
}

to remove the last "-" if this is generated from the first line "preg_replace". Also i've replaced the timestamp with the unique Sku,becose sometime in the automated import process the time() of two adjacent records can be the same, so it isn't unique.

Now the function is:

public function createUrlKey($title, $sku)
{
 $url = preg_replace('#[^0-9a-z]+#i', '-', $title);
 $lastCharTitle = substr($title, -1);
 $lastUrlChar = substr($url, -1);
 if ($lastUrlChar == "-" && $lastCharTitle != "-"){
 $url = substr($url, 0, strlen($url) - 1);
 }
 $urlKey = strtolower($url);
 $storeId = (int) $this->_storeManager->getStore()->getStoreId();
 $isUnique = $this->checkUrlKeyDuplicates($sku, $urlKey, $storeId);
 if ($isUnique) {
 return $urlKey;
 } else {
 return $urlKey . '-' . $sku;
 }
}
answered Jul 19, 2017 at 15:36
1

Magento2 uses the product name to generate the url automatically. So if you have more than one product with the same name, you'll get this error when trying to load subsequent products.

My advice would be to either make the product names distinct - so if you have a configurable product named 'BROWN SHIRT' - you'd load simple products 'BROWN SHIRT - S', 'BROWN SHIRT - L', etc.

Otherwise, if you may have products with the same name then you'll need to create your own URL keys:

Perhaps add the SKU or something else unique to the product name in the key; e.g. "url_key":"sku001-brown-shirt", etc

answered Jun 23, 2017 at 15:17
3
  • Thanks .. So by default in magento 2 there is no any function that check it is unique url key or not ? Commented Jun 23, 2017 at 17:06
  • There is a function that checks if it's unique, but it will throw an error if it's not :) Commented Jun 26, 2017 at 4:59
  • Magento 1 was a little different, from memory it would add an integer suffix. You could try to override the core functionality to mirror this - but I think it's a better option to specify the url_keys yourself - a lot cleaner and at least you have control. Commented Jun 26, 2017 at 5:00
0

has anyone already faced the problem in Magento 2.2, that you have two different product names and magento creates the same url-key for both? Like:

name: Product Name 1 url-key: product-name-1

name: Product Name 2 url-key: product-name-1

I ́m having this problem right now. I ́m posting two different products with different product names and magento is just adding one product to the store and I wondered why. So I had a look at my posted content and the response from magento. And magento is using the url-key from product 1 for product 2, even though I have two separate posts to the api for these two products. Can ́t explain why magento is doing this and I haven ́t found any solution to it or problem/bug for Magento 2.2, but implement and post my own url-key. I also deleted the url-keys in url_rewrite database.

I ́ve already added lots of products in same kind of post without any problem.

answered Jan 23, 2018 at 9:21
0
0

A more efficient way is to use the url_rewrite collection like the below without using the object manager:

$urlRewriteFactory = $this->_objectManager->create('\Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollection');
 $UrlRewriteCollectionData = $urlRewriteFactory->addFieldToFilter('request_path', ['eq' => $productUrlKey] )->addFieldToFilter('store_id', $this->scopeConfig->storeId);
 $productUrlData = $UrlRewriteCollectionData->getFirstItem();
 $existingProductUrlCount = 0;
 if($productUrlData->getId()){
 $existingProductUrlCount = 1;
 }
 try {
 if ($existingProductUrlCount > 0){
 return true;
 }
 } catch (\Exception $ex) {
 $this->logInfo("Check for URL exists " . $ex->getMessage());
 }
 return false;
Niraj Patel
9533 gold badges39 silver badges84 bronze badges
answered Dec 3, 2019 at 14:00

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.