7

I want to add default products of certain ids(example- 1,5,7,3) to be added to the list of related products always with all the products at the end for the product page and need not store in database, how to add these with related product collection in magento

5

You can write an observer for catalog_product_collection_load_after, then add products to the loaded collection if the collection is the related products collection:

use Mage_Catalog_Model_Product as Product;
use Mage_Catalog_Model_Product_Link as RelatedProduct;
use Mage_Catalog_Model_Resource_Product_Link_Product_Collection as RelatedProductCollection;

class IntegerNet_AutoRelated_Model_Observer
{
    /**
     * @see event catalog_product_collection_load_after
     * @param Varien_Event_Observer $observer
     * @throws Mage_Core_Exception
     */
    public function addToRelatedCollection(Varien_Event_Observer $observer)
    {
        $collection = $observer->getCollection();
        if ($collection instanceof RelatedProductCollection
            && $collection->getLinkModel()->getLinkTypeId() === RelatedProduct::LINK_TYPE_RELATED
        ) {
            $this->addItems($collection);
        }
    }

    protected function addItems(RelatedProductCollection $collection)
    {
        /** @var Mage_Catalog_Model_Resource_Product_Collection $productsToAdd */
        $productsToAdd = Mage::getResourceModel('catalog/product_collection');
        $productsToAdd
            ->addStoreFilter()
            ->addIdFilter(array_diff([1,5,7,3], [$collection->getProduct()->getId()], $collection->getAllIds()))
            ->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInCatalogIds());
            ->addMinimalPrice()
            ->addFinalPrice()
            ->addTaxPercents()
            ->setPageSize($numberOfItems)
            ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
            ->addUrlRewrite();
        foreach ($productsToAdd as $product) {
            $collection->addItem($product);
        }
    }
}

Some parts that I'd like to highlight:

->addIdFilter(array_diff([1,5,7,3], [$collection->getProduct()->getId()], $collection->getAllIds()))

This loads the products [1,5,7,3] but excludes the product itself and the products that are already manually defined as related products. Otherwise we would get an error due to duplicates in the collection. You probably want to move these hard coded ids to a configuration.

->addMinimalPrice()
->addFinalPrice()
->addTaxPercents()
->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
->addUrlRewrite();

This prepares the product collection to load the necessary data to display prices, the product link and any attributes configured as "used in product listing", but not more.

This is a very similar solution as in my AutoUpsell module described in Get product list by category id in view.phtml, I copied most of the code from there with slight modifications.

5

You can do this with the help of a custom observer method. To do so, call your observer's function at event catalog_product_save_after.

By using this, whenever a product will be saved from admin panel, you can check whether the product has related products assigned or not.

If it has no related products, then you can assign related products (by product ids) programatically.

Suppose the product in which you want to assign related products has id 2 and related ids are 1,5,7 and 3.

Then:

$product = Mage::getModel('catalog/product')->load(2);
if($product)
{
    $sRelatedIds = '1,5,7,3';
    $aRelatedIds = explode(',', $sRelatedIds);
    $aParams = array();
    $nRelatedCounter = 1;

    foreach($aRelatedIds as $id)
    {
        $aRelatedProduct = Mage::getModel('catalog/product')->load($id);
        $aParams[$aRelatedProduct['entity_id']] = array('position' => $nRelatedCounter);
        $nRelatedCounter++;
    }

    $product->setRelatedLinkData($aParams);
    $product->save();
}

Please let me know if you have any questions.

  • I need to add some of the products always related, to all the products in my store but need not store in database, – mano Jul 27 '16 at 7:02
  • i just want to add the default related products in the product page programmatically not with database , so I'm looking the file at \app\code\core\Mage\Catalog\Block\Product\List\Related.php to add the default with the collection , how to add the product with that collection? – mano Jul 27 '16 at 7:03
  • Sorry, but I could not understand what do you want to say in your last comment? – Mohit Kumar Arora Jul 27 '16 at 7:21
  • i just want to add products of id 1,5,7,3 as related to all the products in the store , I don't want to store that in database . – mano Jul 27 '16 at 7:24
-2

Create new file in \app\code\local\Mage\Catalog\Block\Product\List\Related.php and look for the method and replace with below code:

protected function _prepareData()
{
    $product = Mage::registry('product');
    /* @var $product Mage_Catalog_Model_Product */

    $this->_itemCollection = $product->getRelatedProductCollection()
        ->addAttributeToSelect('required_options')
        ->setPositionOrder()
        ->addStoreFilter();

    foreach ($this->_itemCollection as $product) {
        $productIds1[] = $product->getId();   // here we are getting the product ids of related products of current product.
    }

    $productIds = [1, 5, 7, 3];    // here you can set product id you want to show by default in all products.
    $productscoll1 = Mage::getModel('catalog/product')->getCollection()
        ->addAttributeToFilter('entity_id', ['in' => $productIds]);

    $productscoll1->getSelect()->order("find_in_set(entity_id,'" . implode(',', $productIds) . "')");

    $productscoll2 = Mage::getModel('catalog/product')->getCollection()
        ->addAttributeToFilter('entity_id', ['in' => $productIds1]);
    $productscoll2->getSelect()->order("find_in_set(entity_id,'" . implode(',', $productIds) . "')");

    // print_r($productscoll1->getAllIds());
    // print_r($productscoll2->getAllIds());

    $merged_ids = array_merge($productscoll1->getAllIds(), $productscoll2->getAllIds());   // here we merge both collection ids.
    // can sometimes use "getLoadedIds()" as well

    //print_r($merged_ids);
    //exit;

    $this->_itemCollection = Mage::getModel('catalog/product')->getCollection()
        ->addAttributeToFilter('entity_id', ['in' => $merged_ids]);

    // In this we set collection with default products merge with related products

    if (Mage::helper('catalog')->isModuleEnabled('Mage_Checkout')) {
        Mage::getResourceSingleton('checkout/cart')->addExcludeProductFilter($this->_itemCollection,
            Mage::getSingleton('checkout/session')->getQuoteId()
        );
        $this->_addProductAttributesAndPrices($this->_itemCollection);
    }
    //        Mage::getSingleton('catalog/product_status')->addSaleableFilterToCollection($this->_itemCollection);
    Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($this->_itemCollection);

    $this->_itemCollection->load();

    foreach ($this->_itemCollection as $product) {
        $product->setDoNotUseCategoryId(true);
    }

    return $this;
}
  • can you add comments in each stage so that we can understand that how it works. – mano Jul 27 '16 at 8:23
  • 1
    Also copy the file to path " \app\code\local\Mage\Catalog\Block\Product\List\Related.php " so the changes will not remove at time of upgrade magento. – Chirag Rajput Jul 27 '16 at 8:37
  • 1
    Please don't make changes directly in magento's core files. It is always better to override core magento files to prevent issues while upgrading magento. – Mohit Kumar Arora Jul 27 '16 at 8:37
  • 1
    Rewriting the class is a valid approach (although not necessary), but you load a full collection three times, which is not a good idea performance-wise. Could be improved with $ids = array_merge([1,3,5,7], $product->getRelatedProductCollection()->getAllIds()); followed by a single load with addIdFilter($ids) – Fabian Schmengler Jul 27 '16 at 10:34
  • 1
    actually it's not three loads but two, plus two additional queries for IDs: first (implicit) load: foreach ($this->_itemCollection, two queries for IDs: array_merge($productscoll1->getAllIds(), $productscoll2->getAllIds()); , second load: $this->_itemCollection->load();. With my suggestion above you would halve that to one ID query and one collection load – Fabian Schmengler Jul 27 '16 at 12:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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