Question

I need to change the visibility of 25k products in 28 storeviews.

My first solution works, but is unbearably (10+ minutes for 50- products) slow because of the save()-call. The $brandsToStoreViewIds var is just a mapping of the brand to different storeviews (where it should be visible or not).

Mage::app()->setCurrentStore( Mage_Core_Model_App::ADMIN_STORE_ID );

$products = Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect( 'brand');

foreach( $products as $product ) {
    foreach( $brandsToStoreViewIds as $brand => $storeViewIds ) {
        if( $brand != $product->getAttributeText( 'brand' ) ) {
            foreach( $storeViewIds as $storeViewId ) {
                $product->setStoreId( $storeViewId )->setVisibility( Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE )->save();
            }
        }
    }
}

So i tried to do the same with $product->getResource()->saveAttribute( $product, 'store_id' ):

Mage::app()->setCurrentStore( Mage_Core_Model_App::ADMIN_STORE_ID );

$products = Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect( 'brand');

foreach( $products as $product ) {
    foreach( $brandsToStoreViewIds as $brand => $storeViewIds ) {
        if( $brand != $product->getAttributeText( 'brand' ) ) {
            foreach( $storeViewIds as $storeViewId ) {
                $product->setStoreId( $storeViewId )->setVisibility( Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE );
                $product->getResource()->saveAttribute( $product, 'store_id' );
                $product->getResource()->saveAttribute( $product, 'visibility' );
            }
        }
    }
}

This is supposed to be much faster, but i get the following fatal error:

Fatal error: Call to a member function getBackend() on a non-object in /app/code/core/Mage/Eav/Model/Entity/Abstract.php on line 1536

I think i need to prepare/manipulate the collection so that the store_id can be saved, but do not really know how to achieve this.

Maybe there is an even easier way to hide certain products from storeviews and i'm doing it completely wrong?

Was it helpful?

Solution

You can use the mass attribute update action for that.

// get the products using a collection
$collection = Mage::getResourceModel('catalog/product_collection');
$product_ids = $collection->getAllIds();

// mass update per store view
$action = Mage::getModel('catalog/resource_product_action');
$storeview_ids = array(1,2,3,...);

foreach ($storeview_ids as $storeid)
{
   $action->updateAttributes($product_ids, array(
      'visibility' => Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE
   ), $storeid);
}

OTHER TIPS

This is faster:

$productIds = array(1,2,3);//get the product ids somehow
$attributes = array('visibility'=>Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE);
$storeIds = array(3,4,5,6);//get the store ids somehow
foreach ($storeIds as $storeId){
    Mage::getSingleton('catalog/product_action')->updateAttributes($productIds, $data, $storeId);
}

If you have 25k products then maybe you can break them in sets of 5k and use the code above.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top