Hi,
I am using Magento Enterprise Edition 1.13.1.0
Running Multiple Store in Following Order:
We have multiple categories setup on Default Scope and change their status on each specific store.
The problem is occasionally we get some random numbers added to category URL_KEYS.
We have checked for duplicate url_key+store_id and duplicate request_path+store_id but there are none.
The problem does get resolve if we clear the enterprise_url_rewrite and run reindex, but after some time the issue appears again. So we would like to see a permanent solution to this problem.
There are couple of similar problems on stackoverflow but they are related to Community Edition, As I noticed EE uses a separate module for URL Rewrites so those solutions appear to have no affect.
AFAIK below are the 2 functions which handle URL rewrites and adding numbers to them in Enterprise Edition
Enterprise_Catalog_Model_Index_Action_Url_Rewrite_Category_Refresh > _reindexCategoryUrlKey
$requestPath = trim($category->getParentUrl(), '/'); $requestPath = (!empty($requestPath) ? $requestPath . '/' : '') . $category->getUrlKey(); $requestPath = $this->_cutRequestPath($requestPath); $urlKeyValue = $this->_getUrlKeyAttributeValueId($category, $store); /* * if this category created on store view level, we should write default url key for this category, * or this category will be unaccessible from frontend */ if (empty($urlKeyValue) && empty($urlKeyValue['value_id'])) { $category = $this->_setUrlKeyForDefaultStore($category, $store); //get url key value id from backend table after changes $urlKeyValue = $this->_getUrlKeyAttributeValueId($category, $store); } $valueId = $urlKeyValue['value_id']; /** * Check if we should insert rewrite into table */ $rewriteRow = $this->_getRewrite($requestPath, $store->getId()); if (!$rewriteRow || $rewriteRow['value_id'] != $valueId) { //get current url path from enterprise_url_rewrite $rewriteForValueId = $this->_getRewriteForValueId($store->getId(), $valueId); $suffix = trim(str_replace($requestPath, '', $category->getRequestPath()), '-'); /* * theoretically we may face with situation when several categories have url_key like: * id url_key request path * 1 abc abc * 2 abc abc-1 * 3 abc abc-2 * and we should reindex category with id 2, we can't be sure should we add prefix or not * so workaround with regexp cover most cases of this problem */ $requestPathIncrement = (int) $this->_getRewriteRequestIncrement($requestPath, $store); if (!$rewriteForValueId || !preg_match('#^(\d)+$#', $suffix) || ($suffix > $requestPathIncrement)) { if ($rewriteRow && $rewriteRow['value_id'] != $valueId) { $requestPath .= '-' . ++$requestPathIncrement; } $category = $this->_saveRewrite($category, $store, $requestPath, $valueId); // clean full page cache for category } } // save id of already indexed category into list $this->_indexedCategoryIds[$store->getId()][$category->getId()] = 1; return $category;
Enterprise_Catalog_Model_Index_Action_Url_Rewrite_Category_Refresh > _getRewriteRequestIncrement
// match request_url abcdef1234(-12)(.html) pattern $match = array(); $regularExpression = '#^([0-9a-z/-]+)(-([0-9]+))?$#i'; preg_match($regularExpression, $urlPath, $match); $match[1] = $match[1] . '-'; $match[4] = isset($match[4]) ? $match[4] : ''; $prefix = $match[1]; $requestPathField = new Zend_Db_Expr($this->_connection->quoteIdentifier('request_path')); //select increment part of request path and cast expression to integer $urlIncrementPartExpression = $this->_eavHelper->getCastToIntExpression( $this->_connection->getSubstringSql( $requestPathField, strlen($prefix) + 1, $this->_connection->getLengthSql($requestPathField) . ' - ' . strlen($prefix) ) ); $select = $this->_connection->select() ->from( $this->_getTable('enterprise_urlrewrite/url_rewrite'), new Zend_Db_Expr('MAX(' . $urlIncrementPartExpression . ')') ) ->where('entity_type = :entity_type') ->where('store_id = :store_id') ->where('request_path LIKE :request_path') ->where( $this->_connection->prepareSqlCondition( 'request_path', array( 'regexp' => '^' . preg_quote($prefix) . '[0-9]*$', ) ) ); $bind = array( 'store_id'=> (int) $store->getId(), 'request_path' => $prefix . '%', 'entity_type' => Enterprise_Catalog_Model_Category::URL_REWRITE_ENTITY_TYPE, ); return (int)$this->_connection->fetchOne($select, $bind);
So I went ahead and overridden these but still not sure which line of code to modify to fix this issue.
Kindly feel free to ask if you need more information, Any help would be highly appreciated.
Thank You,
Z
Solved! Go to Solution.
It turns out there is some nasty bug in EE 1.13 when stores with different language and same url keys exist.
I was unable to find the root cause of this issue but here is my solution: I overriden the `Enterprise_Catalog_Model_Index_Action_Url_Rewrite_Category_Refresh` class in a custom module and than modified `_reindexCategoryUrlKey` as follows
protected function _reindexCategoryUrlKey(Mage_Catalog_Model_Category $category, Mage_Core_Model_Store $store) { $requestPath = trim($category->getParentUrl(), '/'); $requestPath = (!empty($requestPath) ? $requestPath . '/' : '') . $category->getUrlKey(); $requestPath = $this->_cutRequestPath($requestPath); $urlKeyValue = $this->_getUrlKeyAttributeValueId($category, $store); /* * if this category created on store view level, we should write default url key for this category, * or this category will be unaccessible from frontend */ if (empty($urlKeyValue) && empty($urlKeyValue['value_id'])) { $category = $this->_setUrlKeyForDefaultStore($category, $store); //get url key value id from backend table after changes $urlKeyValue = $this->_getUrlKeyAttributeValueId($category, $store); } $valueId = $urlKeyValue['value_id']; /** * Check if we should insert rewrite into table */ $rewriteRow = $this->_getRewrite($requestPath, $store->getId()); if (!$rewriteRow || $rewriteRow['value_id'] != $valueId) { //get current url path from enterprise_url_rewrite $rewriteForValueId = $this->_getRewriteForValueId($store->getId(), $valueId); $suffix = trim(str_replace($requestPath, '', $category->getRequestPath()), '-'); $requestPathIncrement = (int)$this->_getRewriteRequestIncrement($requestPath, $store); if (!$rewriteForValueId || !preg_match('#^(\d)+$#', $suffix) || ($suffix > $requestPathIncrement)) { if ($rewriteRow && $rewriteRow['value_id'] != $valueId) { /* * disabled request path increment here * skip URL Rewrite if URL_KEY is same. */ } else { $category = $this->_saveRewrite($category, $store, $requestPath, $valueId); } } } // save id of already indexed category into list $this->_indexedCategoryIds[$store->getId()][$category->getId()] = 1; return $category; } // _reindexCategoryUrlKey
as you will notice, i modified below part of the function:
if ($rewriteRow && $rewriteRow['value_id'] != $valueId) { $requestPath .= '-' . ++$requestPathIncrement; } $category = $this->_saveRewrite($category, $store, $requestPath, $valueId);
with this:
if ($rewriteRow && $rewriteRow['value_id'] != $valueId) { /* * disabled request path increment here * skip URL Rewrite if URL_KEY is same. */ } else { $category = $this->_saveRewrite($category, $store, $requestPath, $valueId); }
then i cleared `enterprise_url_rewrites` table and run reindex. Now everything appears to be working fine.
Note: This solution has its own limitations i.e. if you create a duplicate url_key only the first category will work, you will need to update url_key of newer category to be different in order for them to visible on frontend.
Thank You
I believe there is a patch for this. Please open a ticket in the support portal for Magento Enterprise.
It turns out there is some nasty bug in EE 1.13 when stores with different language and same url keys exist.
I was unable to find the root cause of this issue but here is my solution: I overriden the `Enterprise_Catalog_Model_Index_Action_Url_Rewrite_Category_Refresh` class in a custom module and than modified `_reindexCategoryUrlKey` as follows
protected function _reindexCategoryUrlKey(Mage_Catalog_Model_Category $category, Mage_Core_Model_Store $store) { $requestPath = trim($category->getParentUrl(), '/'); $requestPath = (!empty($requestPath) ? $requestPath . '/' : '') . $category->getUrlKey(); $requestPath = $this->_cutRequestPath($requestPath); $urlKeyValue = $this->_getUrlKeyAttributeValueId($category, $store); /* * if this category created on store view level, we should write default url key for this category, * or this category will be unaccessible from frontend */ if (empty($urlKeyValue) && empty($urlKeyValue['value_id'])) { $category = $this->_setUrlKeyForDefaultStore($category, $store); //get url key value id from backend table after changes $urlKeyValue = $this->_getUrlKeyAttributeValueId($category, $store); } $valueId = $urlKeyValue['value_id']; /** * Check if we should insert rewrite into table */ $rewriteRow = $this->_getRewrite($requestPath, $store->getId()); if (!$rewriteRow || $rewriteRow['value_id'] != $valueId) { //get current url path from enterprise_url_rewrite $rewriteForValueId = $this->_getRewriteForValueId($store->getId(), $valueId); $suffix = trim(str_replace($requestPath, '', $category->getRequestPath()), '-'); $requestPathIncrement = (int)$this->_getRewriteRequestIncrement($requestPath, $store); if (!$rewriteForValueId || !preg_match('#^(\d)+$#', $suffix) || ($suffix > $requestPathIncrement)) { if ($rewriteRow && $rewriteRow['value_id'] != $valueId) { /* * disabled request path increment here * skip URL Rewrite if URL_KEY is same. */ } else { $category = $this->_saveRewrite($category, $store, $requestPath, $valueId); } } } // save id of already indexed category into list $this->_indexedCategoryIds[$store->getId()][$category->getId()] = 1; return $category; } // _reindexCategoryUrlKey
as you will notice, i modified below part of the function:
if ($rewriteRow && $rewriteRow['value_id'] != $valueId) { $requestPath .= '-' . ++$requestPathIncrement; } $category = $this->_saveRewrite($category, $store, $requestPath, $valueId);
with this:
if ($rewriteRow && $rewriteRow['value_id'] != $valueId) { /* * disabled request path increment here * skip URL Rewrite if URL_KEY is same. */ } else { $category = $this->_saveRewrite($category, $store, $requestPath, $valueId); }
then i cleared `enterprise_url_rewrites` table and run reindex. Now everything appears to be working fine.
Note: This solution has its own limitations i.e. if you create a duplicate url_key only the first category will work, you will need to update url_key of newer category to be different in order for them to visible on frontend.
Thank You