I am trying to customize my product landing pages to include all a scrollable view of all other products within the same category. I have it almost there, but it is showing products from all categories, rather than just the category the current product you are viewing is in. Below is the code I have added to my product view.phtml, which gives me the products in my scrollable container. Can any one help me limit it to show only products in the current category? A sample of one of the product pages can be viewed at Product view page
The version is magento 1.6.1
My product view customization here
<div class="coll_container">
<!-- "previous page" action -->
<a class="prev browse left"></a>
<div id="collection" class="scrollable">
<?php
$cat_id = Mage::getModel('catalog/layer')->getCurrentCategory()->getId(); // set current category id
$category = Mage::getModel('catalog/category')->load($cat_id);
$productCollection = Mage::getResourceModel('catalog/product_collection')
->addCategoryFilter($category);
$products = $category->getProductCollection()->addCategoryFilter($category)->addAttributeToSelect('*');
?>
<ul>
<?php foreach ( $products as $_product ): ?>
<li class="item"><?php if($_product->isComposite() || !$_product->isSaleable()): ?>
<?php endif; ?>
<a class="item-link" href="<?php echo $_product->getProductUrl() ?>"><img src="<?php echo $this->helper('catalog/image')->init($_product, 'thumbnail')->keepAspectRatio(true)->keepFrame(false)->resize(150,225) ?>" alt="<?php echo $this->htmlEscape($_product->getName()) ?>" width="150" height="225" /></a>
<div class="tooltip">
<span class="indicator"><!-- --></span>
<div class="tooltip-content">
<a href="<?php echo $_product->getProductUrl() ?>"><?php echo $this->htmlEscape($_product->getName()) ?></a>
<!-- Price -->
<p class="price"> <?php echo $this->getPriceHtml($_product, true) ?> </p>
</div><!-- End Tooltip content -->
</div><!-- End Tooltip -->
</li>
<?php endforeach; ?>
</ul>
</div><!-- End Collection -->
<!-- "next page" action -->
<a class="next browse right"></a>
</div><!-- End coll_container -->
Besides the redundancy of getting the collection twice - $productCollection
and $products
, the latter one being used for the loop - your code would work correctly and the collection would contain only products of the current category, provided your landing pages are rewritten to
catalog/category/view/id/<id> OR
catalog/product/view/id/<id>/category/<id>
but not, if they are rewritten to
catalog/product/view/id/<id>
This is because Mage_Catalog_Model_Layer::getCurrentCategory()
depends on whether the registry key current_category
is set. If current_category
is not set, the method returns the root category id of the current store, which explains why you see products of all categories:
public function getCurrentCategory()
{
$category = $this->getData('current_category');
if (is_null($category)) {
if ($category = Mage::registry('current_category')) {
$this->setData('current_category', $category);
}
else {
$category = Mage::getModel('catalog/category')->load($this->getCurrentStore()->getRootCategoryId());
$this->setData('current_category', $category);
}
}
return $category;
}
In Magento OOB, the registry key current_category
will be set at different locations, but in your case only these two are of interest:
Mage_Catalog_CategoryController::_initCatagory()*
Mage_Catalog_Helper_Product::initProduct()
The former is normally only called by
Mage_Catalog_CategoryController::viewAction()
The latter is called at several places, amongst others at
Mage_Catalog_ProductController::viewAction()
but in this case only, if a catalog
parameter like catalog/<id>
was passed.
One possibility to fix your issue would be to add rewrites for your landing pages that use
catalog/product/view/id/1/category/3
style target_path
s.
If you only have a handfull of products, you can do this manually using the "URL Rewrite Management" in the admin backend.
If you have many products, you can also do it programmatically.
Another possibility to fix this issue would be, to get the category id directly from the product being viewed and use it to filter the collection:
$aCategoryId = $this->getProduct()->getCategoryIds();
if (!$aCategoryId) {
echo "This product is not assigned to any categories.";
}
$iCategoryId = $aCategoryId[0];
$oCategory = Mage::getModel('catalog/category')->load($iCategoryId);
$oProductCollection = $oCategory
->getProductCollection()
->addCategoryFilter($oCategory)
->addAttributeToSelect('*')
->addFieldToFilter('entity_id', array('neq' => $this->getProduct()->getId()));
foreach ($oProductCollection as $oProduct) {
var_dump($oProduct->getName());
}
Note, that I added a filter to exclude the viewed product itself from the collection.
* that's not a typo, it is really written a _initCatagory
, not _initCategory
in at least CE 1.6.2 (haven't checked others, yet)