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 ?

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;
    }
}
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;
    }
}
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

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 :)
    – BAF
    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.
    – BAF
    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.

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;

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.