4

We are having a problem in our Magento 2.1.3 shop when we try to save the categories. We are getting the message URL for a key for specified store already exists.

The shop is a migration from a Magento 1 shop and has several root categories and stores. There are in the different root categories with the same name.

Till now we could not really find connections where it gives the error and sometimes it does not give the error.

Is there anyone with experience with this error that knows why this is happening?

1

This issue happens when the URL rewrite you are trying to create already exists for that store.

For example, if you had 2 categories both named clothing and tried to set the url_key for each to clothing-category Magento wouldn't let you save the 2nd category because the URL example.com/clothing-category is already being used.

It might not necessarily be another category URL rewrite that is conflicting either. If you had a cms page or any other entity already using that URL Magento would show that same error.

| improve this answer | |
  • Hi Andrew, thank you so much for your reply. In our case we have 10 root categories with subcategories and there are a lot of categories with the same url_key. So for instance root store 1 has 3 shops (so different urls .nl / .be / .fr) connected to it and category with url_key parasol. Then there is another root category with also two shops connected to it that also has the subcategory parasol. In Magento 1 this was just working, how could you get this to work in Magento 2? – Coen Feb 10 '17 at 8:41
  • Hi Andrew, I also just did a test in which I made in two root categories (same as above) the category "test1" with 4 products and this seems to go fine, so it is possible to have the same url_key when you make new categories. It looks like it has also something to do with the migration – Coen Feb 10 '17 at 8:47
1

This Magento 2 bug you can directly fix is changing the file.

File Path:

vendor/magento/module-url-rewrite/Model/Storage/DbStorage.php

Orginal Code:

from

protected function doReplace($urls)
{
    foreach ($this->createFilterDataBasedOnUrls($urls) as $type => $urlData) {
        $urlData[UrlRewrite::ENTITY_TYPE] = $type;
        $this->deleteByData($urlData);
    }
    $data = [];
    foreach ($urls as $url) {
        $data[] = $url->toArray();
    }
    $this->insertMultiple($data);
}

into

protected function doReplace($urls)
{
    foreach ($this->createFilterDataBasedOnUrls($urls) as $type => $urlData) {
        $urlData[UrlRewrite::ENTITY_TYPE] = $type;
        $this->deleteByData($urlData);
    }
    $data = [];
    foreach ($urls as $url) {
        $data[] = $url->toArray();
    }

     /* Add this line : Get rid of rewrite for root Magento category to unduplicate things
    foreach($data as $key =>$info){
            if(isset($info['target_path']) && stristr($info['target_path'],'/category/1') && $info['entity_type']=='product'){
                    unset($data[$key]);
            }
    }

    $this->insertMultiple($data);
}

After inserting this line clear cache.

| improve this answer | |
0

I have fixed this issue in more than 3-4 projects.

If you want to resolve this issue, you can upgrade your version with latest one or try below code logic:

Try this solution by overriding below function in your custom module :)

Path: vendor/magento/module-url-rewrite/Model/Storage

protected function doReplace(array $urls){ 
    $this->deleteOldUrls($urls); 
    $data = [];
    $storeId_requestPaths = [];
    foreach ($urls as $url) {
        $storeId = $url->getStoreId();
        $requestPath = $url->getRequestPath();
        $sql = "SELECT * FROM url_rewrite where store_id = $storeId and request_path = '$requestPath'";
        $exists = $this->connection->fetchOne($sql); 
        if ($exists) continue;
        $storeId_requestPaths[] = $storeId . '-' . $requestPath;
        $data[] = $url->toArray();
    }

    // Remove duplication data;
    $n = count($storeId_requestPaths);
    for ($i = 0; $i < $n - 1; $i++) {
        for ($j = $i + 1; $j < $n; $j++) {
            if ($storeId_requestPaths[$i] == $storeId_requestPaths[$j]) {
                unset($data[$j]);
            }
        }
    }
    try {
        $this->insertMultiple($data);
    } catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
        /** @var \Magento\UrlRewrite\Service\V1\Data\UrlRewrite[] $urlConflicted */
        $urlConflicted = [];
        foreach ($urls as $url) {
            $urlFound = $this->doFindOneByData(
                [
                    UrlRewriteData::REQUEST_PATH => $url->getRequestPath(),
                    UrlRewriteData::STORE_ID => $url->getStoreId(),
                ]
            );
            if (isset($urlFound[UrlRewriteData::URL_REWRITE_ID])) {
                $urlConflicted[$urlFound[UrlRewriteData::URL_REWRITE_ID]] = $url->toArray();
            }
        }
        if ($urlConflicted) {
            throw new \Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException(
                __('URL key for specified store already exists.'),
                $e,
                $e->getCode(),
                $urlConflicted
            );
        } else {
            throw $e->getPrevious() ?: $e;
        }
    }

    return $urls;
}

Happy Coding :)

Thanks,

Ketan T.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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