0

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?

3

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);
}
  • works great, it's even fast enough to put in into an save/import event, so i don't even need to care about it anymore :) – Marc Harding Nov 12 '13 at 11:04
  • Good to hear! If you have a problem it's always good to search for a solution Magento already implements themselves. :) – Sander Mangel Nov 12 '13 at 12:24
1

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.

  • thanks for your answer! this works much faster then my initial try (about 10 seconds for my test set, before that it was more like 20 minutes). but sanders method is even faster ( 0,5 seconds). thanks again and greetings to romania, i was just in sibiu a few weeks ago :) – Marc Harding Nov 12 '13 at 10:06
  • @myel. Then +1 for Sander from me :). – Marius Nov 12 '13 at 10:10

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.