27

What is the most efficient way of getting a product url given just it's ID? In a few places in our code we have things such as Mage::getModel('catalog/product')->load($id)->getProductUrl() in order to get the URL of the product, given the amount of events etc associated with a product this seems rather wasteful, is there a simpler method? The ability to also specify a category id would be nice.

Additionally, is there an efficient method for doing the same thing for a single attribute for a product such as name?

1
  • 1
    did your question get solved here? Did you need more help on this question? If so let us know what needs to be done to help you find a solution.
    – philwinkle
    Jan 16, 2014 at 16:20

4 Answers 4

47

Interesting to know if we can get the product URL without loading whole product. Sorry to answer your additional question and not the main question, as I am also not sure if we can get it :)

For getting a single attribute without loading whole product, you can use getAttributeRawValue() if you are using Magento CE version 1.6+

Mage::getResourceModel('catalog/product')->getAttributeRawValue($productId, 'attribute_code', $storeId);

As per @philwinkle's comment below, here is more optimized code:

Mage::getResourceSingleton('catalog/product')
  ->getAttributeRawValue($productId, 'attribute_code', Mage::app()->getStore());

UPDATE: Get product URL by ID without loading whole product:

Mage::getResourceSingleton('catalog/product')
  ->getAttributeRawValue($productId, 'url_key', Mage::app()->getStore());
6
  • 8
    Wowzers. Didn't know about that one! Everybody upvote this answer. If you really want to up the ante, you can reuse an existing catalog/product resource model (instead of instantiating a new one) by calling getResourceSingleton instead. $storeId doesn't have to be an id, it can be a Mage_Core_Model_Store object, too, so you can use Mage::app()->getStore() inline to speed things up.
    – philwinkle
    Oct 31, 2013 at 14:04
  • And you can use it to fetch multiple attributes: @param int|string|array $attribute atrribute's ids or codes (in 1.7)
    – Richard
    Oct 31, 2013 at 15:44
  • I like this approach, very neat. I've up-voted. I'll accept if nobody comes up with an answer to the URL. Oct 31, 2013 at 16:55
  • Can this still be used without a product ID? If I only have a SKU, am I forced to load the model?
    – pspahn
    May 20, 2015 at 18:44
  • 1
    Note that in case there are more than a product with the same url_key this may not work because magento gonna create a different url rewrite from the url_key
    – Fra
    Mar 12, 2018 at 10:01
11

I think it would be beneficial to do this via a collection. If you do not need the complete product information then you could load it via a collection and so only load information you need. The code would be as follows.

$product_collection = Mage::getModel('catalog/product')->getCollection()
    ->addAttributeToFilter('entity_id', 16)
    ->addUrlRewrite();
$product_collection_url = $product_collection->getFirstItem()->getProductUrl();

Note: the addUrlRewrite so that you can get the product url later, this can also take a category id as a parameter, without this the url would not contain the category.

You are still end up calling the getProductUrl() which ends up using Mage_Catalog_Model_Product_Url, but this only needs the id, request_path and the url key so it should work without the full product.

2
  • This works good! Mar 27, 2014 at 11:31
  • It would seem that $Product->getProductUrl() should be all you need. The "addUrlRewrite()" addition makes the difference - thanks for providing that example.
    – jschrab
    Feb 19, 2016 at 17:21
5

I guess the most efficent way to get a products rewritten URL (w/o loading product) is to look directly on URL rewrite talbe.

# returns string "product-url.html"
$productUrl = Mage::getResourceModel('core/url_rewrite')
    ->getRequestPathByIdPath('product/' . $productId, $storeId);

To get full category path, use

# returns string "full/category/path/product-url.html"
$productUrl = Mage::getResourceModel('core/url_rewrite')
    ->getRequestPathByIdPath('product/' . $productId . '/' . $categoryId, $storeId);

Edit: tested for "url_key", for other attributes getAttributeRawValue should fit.

  1. getRequestPathByIdPath

    • Total Incl. Wall Time (microsec): 8,323 microsecs
    • Total Incl. CPU (microsecs): 8,038 microsecs
    • Total Incl. MemUse (bytes): 273,872 bytes
    • Total Incl. PeakMemUse (bytes): 213,488 bytes
    • Number of Function Calls: 372
  2. getAttributeRawValue

    • Total Incl. Wall Time (microsec): 51,213 microsecs
    • Total Incl. CPU (microsecs): 50,390 microsecs
    • Total Incl. MemUse (bytes): 1,223,520 bytes
    • Total Incl. PeakMemUse (bytes): 1,168,496 bytes
    • Number of Function Calls: 2,233
  3. load(productId)

    • Total Incl. Wall Time (microsec): 605,649 microsecs
    • Total Incl. CPU (microsecs): 598,820 microsecs
    • Total Incl. MemUse (bytes): 5,370,848 bytes
    • Total Incl. PeakMemUse (bytes): 5,314,384 bytes
    • Number of Function Calls: 27,774
3

I found this question, wondering the same. And just in case someone else needs this sometime, I'll post my own findings here.

I found two methods of getting the product URL without loading the complete product. Since I was working on a slow server, I needed to find the fastest loading method.

The first method:

The first get's a product collection based on the product ID:

$_item = Mage::getModel('catalog/product')->getCollection()
    ->addAttributeToSelect('product_url')
    ->addAttributeToFilter('entity_id', $productId)
    ->addUrlRewrite()
    ->load();

foreach($_item as $product){
    echo $product->getProductUrl();
}

// returns string "http://www.your-domain.com/[category]/[product_url]"

The second method:

The second method, using Kalpesh Metha's method, would be this code:

Mage::getResourceSingleton('catalog/product')
      ->getAttributeRawValue($productId, 'url_key', Mage::app()->getStore());

// returns string "product-url-like-this"

For this method, you can either use 'url_key' or 'url_path'. I have not found out the difference though.

The difference between the methods:

The first method takes slightly more time (about 15% time extra). The second method however, only returns the final part of the URL. This means that if the shop uses the category in the URL, it won't work, since that part isn't shown. This was the case in the shop I was working on.

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