dscc90150010 2019-01-25 11:48
浏览 194
已采纳

Magento 2 URL重写问题:指定商店已存在URL密钥

I am facing this issue while saving a product programmatically on Magento 2.2.5

In any module, if I do $product->save(); OR $this->productRepository->save($product); inside a loop for multiple products. I get:

PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'the-lipstick.html-1' for key 'URL_REWRITE_REQUEST_PATH_STORE_ID' in /home/dev3/www/vendor/magento/zendframework1/library/Zend/Db/Statement/Pdo.php:228

The error is similar to the one described here : https://www.human-element.com/url-key-specified-store-already-exists-magento-2/

Products save fine with admin area login.

Any suggested fixes so far including the ones modifying the core files (DBStorage.php) do not work on 2.2.5.

What I tried so far: 1. Fix from https://www.human-element.com/url-key-specified-store-already-exists-magento-2/ 2. Fix from https://magento.stackexchange.com/questions/210359/magento-2-product-url-rewrite-issue

Please suggest a solution/fix for M 2.2.5

  • 写回答

3条回答 默认 最新

  • dreljie602951 2019-07-22 05:49
    关注

    My Fix : In di.xml -

    <preference for="Magento\UrlRewrite\Model\Storage\DbStorage" type="MyCompany\FixUrls\Model\ProductUrlFix" />

    In ProductFixUrl write these two functions :

    protected function doReplace(array $urls){
    
        $this->deleteOld($urls);
            $data = [];
            $storeId_requestPaths = [];
    
            foreach ($urls as $url) {
                $storeId = $url->getStoreId();
                $requestPath = $url->getRequestPath();
                // Skip if is exist in the database
                $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();
            }
            try {
    
                $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]);
                        }
                    }
                }
                parent::insertMultiple($data);
    
            } catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
                /** @var \Magento\UrlRewrite\Service\V1\Data\UrlRewrite[] $urlConflicted */
                $urlConflicted = [];
                foreach ($urls as $url) {
                    $urlFound = parent::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;
        }
    
        /**
         * @param UrlRewrite[] $urls
         *
         * @return void
         */
        public function deleteOld(array $urls)
        {
            $oldUrlsSelect = $this->connection->select();
            $oldUrlsSelect->from(
                $this->resource->getTableName(self::TABLE_NAME)
            );
            /** @var UrlRewrite $url */
            foreach ($urls as $url) {
                $oldUrlsSelect->orWhere(
                    $this->connection->quoteIdentifier(
                        UrlRewrite::ENTITY_TYPE
                    ) . ' = ?',
                    $url->getEntityType()
                );
                $oldUrlsSelect->where(
                    $this->connection->quoteIdentifier(
                        UrlRewrite::ENTITY_ID
                    ) . ' = ?',
                    $url->getEntityId()
                );
                $oldUrlsSelect->where(
                    $this->connection->quoteIdentifier(
                        UrlRewrite::STORE_ID
                    ) . ' = ?',
                    $url->getStoreId()
                );
            }
    
            // prevent query locking in a case when nothing to delete
            $checkOldUrlsSelect = clone $oldUrlsSelect;
            $checkOldUrlsSelect->reset(Select::COLUMNS);
            $checkOldUrlsSelect->columns('count(*)');
            $hasOldUrls = (bool) $this->connection->fetchOne($checkOldUrlsSelect);
    
            if ($hasOldUrls) {
                $this->connection->query(
                    $oldUrlsSelect->deleteFromSelect(
                        $this->resource->getTableName(self::TABLE_NAME)
                    )
                );
            }
        }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料