cancel
Showing results for 
Search instead for 
Did you mean: 

Magento EE 1.13.1.0 numbers showing in Category URL_KEY

SOLVED

Magento EE 1.13.1.0 numbers showing in Category URL_KEY

Hi,

I am using Magento Enterprise Edition 1.13.1.0
Running Multiple Store in Following Order:

  • Store 1:
    • English
    •     Français
  • Store 2:
    • English
    • Français
  • Store 3:
    • English
    • Français
  • Main Store:
    • Default Store View


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

2 REPLIES

Re: Magento EE 1.13.1.0 numbers showing in Category URL_KEY

Almost 40 people viewed the post but no responses at all, please let me know if i need to put in more clarifications.

Or maybe no one knows a solution to this :-/

Re: Magento EE 1.13.1.0 numbers showing in Category URL_KEY

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