Get rewritten product url in a different store

It was pointed out to me in one of the preceding articles that getting a product’s URL in a different store can get pretty complicated if the URL you want to get is rewritten. I decided to come up with a solution to that problem, as it could be useful in the future.

I came up with a method that returns a rewritten part (i.e. after rewrite) of a product’s URL. You’ll need to add base URL of a store to this return value to get a full URL (as shown on languages.phtml example).

Note that this is useful only if you have a scope of URL key attribute set to store view. This means that you could have different URL of a product in different stores – for example if you have a product with an URL key ‘nokia-blue‘ in english store view, and ‘nokia-blau‘ in german store view. This will work for rewrites that you when editing your product. If you decide to add URL rewrites yourself in ‘URL rewrite management’, you probably have a very good reason, but we won’t be covering that case.

I won’t be going through creating and registering a module this time.

Lets start by adding this method to your module’s helper.

app/code/community/Inchoo/Rewrites/Helper/Data.php

<?php
class Inchoo_Rewrites_Helper_Data extends Mage_Core_Helper_Abstract
{
public function rewrittenProductUrl($productId, $categoryId, $storeId)
{
$coreUrl = Mage::getModel('core/url_rewrite');
$idPath = sprintf('product/%d', $productId);
if ($categoryId) {
$idPath = sprintf('%s/%d', $idPath, $categoryId);
}
$coreUrl->setStoreId($storeId);
$coreUrl->loadByIdPath($idPath);
 
return $coreUrl->getRequestPath();
}
}
?>

Now, we’ll do a little walk-through. As you can see, this method accepts $productId, $categoryId and $storeId as arguments. To understand how URLs look before they’re rewritten, let’s take a look at core_url_rewrite table in our database.

rewritten-product-url-example

A id_path of a product that’s not in any category appears in form of product/productId, and if it belongs to any of the categories, it’s appears as product/productId/categoryId.

Let’s get back to our method. We’ll recreate the structure of id_path using data we already have in Magento registry. Then, we need to setStoreId() to the model we’re using before we look for a rewrite. After that, we’ll use loadByIdPath() to load our rewritten URL row. All that’s left now is getting a request path, i.e. the rewritten part of a product’s URL. We’ll doing all that using Magento’s core/url_rewrite model.

One use case for this would be language (store) switcher that redirects you to the same product you’re looking at, but in different store. Just place the following code in your languages.phtml file.

app/design/base/default/template/page/html/switch/languages.phtml

<?php if(count($this->getStores())>1): ?>
<?php
$helper = Mage::helper('inchoo_rewrites');
$prod = Mage::registry('current_product');
$categ = Mage::registry('current_category');
$categId = $categ ? $categ->getId() : null;
 
?>
<div class="form-language">
<label for="select-language"><?php echo $this->__('Your Language:') ?></label>
<select id="select-language" title="<?php echo $this->__('Your Language') ?>" onchange="window.location.href=this.value">
<?php foreach ($this->getStores() as $_lang): ?>
<?php $_selected = ($_lang->getId() == $this->getCurrentStoreId()) ? ' selected="selected"' : '' ?>
<option value="<?php
if($prod) {
echo $_lang->getBaseUrl() . $helper->rewrittenProductUrl($prod->getId(), $categId, $_lang->getId()) . '?___store=' . $_lang->getCode();
}else{
echo $_lang->getCurrentUrl(false);
}
?>"<?php echo $_selected ?>><?php echo $this->escapeHtml($_lang->getName()) ?></option>
<?php endforeach; ?>
</select>
</div>
<?php endif; ?>

Your language switcher’s source code should look something like this (provided you have different URL set for your product in at least one store)
rewritten-product-url-example-2

Hope this will help some of you to master the concept of URL rewrites in multilingual stores.