Réinitialiser «Utiliser la valeur par défaut» pour une vue de magasin spécifique sur tous les produits

16

D'une manière ou d'une autre, un certain nombre de mes produits avaient la «Utiliser la valeur par défaut» désélectionnée.

Mon magasin a 2 langues, anglais et français. Le français utilise la valeur par défaut du magasin, donc maintenant, lorsque je mets à jour des produits, il n'apparaît pas sur le front-end, sauf si je vais manuellement sur le produit dans la vue du magasin en français et sélectionnez "Utiliser la valeur par défaut",

Il ne semble pas y avoir d'attribut pour une action de masse, j'ai rencontré des scripts et des requêtes MySQL, mais il n'est pas clair si ces solutions réinitialisent toutes les vues de magasin pour utiliser la valeur par défaut.

Le résultat souhaité est de définir "Utiliser la valeur par défaut" sur une vue de magasin spécifique (français) sur tous les produits.

Comment réinitialiser un grand nombre de produits (ou tous les produits) sur "Utiliser la valeur par défaut" sur une vue de magasin spécifique?

SR_Magento
la source

Réponses:

7

Malheureusement, aucun des moyens efficaces de mettre à jour un attribut de produit ne fonctionne dans ce cas. $product->getResource()->saveAttribute()met à jour l'attribut pour toutes les vues de magasin même si vous définissez l'ID de magasin sur l' $productobjet. Mage::getSingleton('catalog/product_action')->updateAttributes()met uniquement à jour la valeur dans un magasin spécifique, mais il ne peut pas définir l'attribut pour utiliser la valeur par défaut (voir également cette question de dépassement de pile pour une référence). Par conséquent, nous devons utiliser le moyen lent et gourmand en mémoire via $product->save().

Je suppose que vous savez quels attributs vous souhaitez mettre à jour. Pour l'exemple suivant, j'ai défini l' visibilityattribut pour utiliser la valeur par défaut. Le script suivant devrait alors faire l'affaire (assurez-vous de le modifier selon vos besoins):

<?php

error_reporting(E_ALL);
ini_set('display_errors', '1');

require_once 'app/Mage.php';
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
set_time_limit(0);

function useDefaultValueCallback($args)
{
    // change to the ID of your french store view
    $specificStoreViewId = 7;
    $product = Mage::getModel('catalog/product');
    $product->setData($args['row']);
    $product->setStoreId($specificStoreViewId);
    // change according to your needs
    $product->setData('visibility', false);
    $product->save();
}

$products = Mage::getModel('catalog/product')->getCollection();
Mage::getSingleton('core/resource_iterator')->walk($products->getSelect(), array('useDefaultValueCallback'));
Simon
la source
Existe-t-il un moyen de cocher la case "utiliser la valeur par défaut" sans modifier les données d'attribut? Parce qu'ici, si je l'utilise, $product->setData('visibility', false);cela cochera la case, mais mettra également la visibilité sur "true", ce que je ne veux pas
Jurģis Toms Liepiņš
1
@ JurģisTomsLiepiņš Si vous cochez la case, il utilise la valeur par défaut, qui est la valeur de la portée parent. Par conséquent, si vous cochez la case et qu'elle passe à "true", votre valeur de portée parent est également "true". Pour d'autres questions, veuillez poser une nouvelle question.
Simon
J'ai posé une nouvelle question , j'espère que vous pourrez clarifier / clarifier certaines choses pour moi
Jurģis Toms Liepiņš
J'utilise le setData à false avec succès (lorsqu'il est appelé à partir de cli). Mais j'ai remarqué que lorsque j'appelle la même fonction à partir d'une route de contrôleur frontal, cela ne fonctionne pas! Quelqu'un est-il déjà confronté à ce problème?
DarkCowboy
@DarkCowboy Il s'agit probablement d'un problème d'autorisation. Je ne pense pas que vous puissiez enregistrer un produit dans un contrôleur frontal. Pour d'autres questions, veuillez en ouvrir une nouvelle.
Simon
24

En supposant que l'ID de magasin pour le magasin français est 2, vous devez exécuter les requêtes mysql ci-dessous:

DELETE FROM `catalog_product_entity_text` where store_id = 2;
DELETE FROM `catalog_product_entity_datetime` where store_id = 2;
DELETE FROM `catalog_product_entity_decimal` where store_id = 2;
DELETE FROM `catalog_product_entity_int` where store_id = 2;
DELETE FROM `catalog_product_entity_varchar` where store_id = 2;

Cela supprime essentiellement les valeurs d'attribut pour tous les attributs et produits pour lesquels l'ID de magasin est défini sur 2. Lorsque Magento ne peut pas trouver la valeur d'attribut pour un produit par rapport à l'ID de magasin particulier, il choisit la valeur par défaut.

Paras Sood
la source
1
Ce n'est pas vrai. Si l'on définit la valeur d'attribut falsecomme je l'ai fait, l'option "Utiliser la valeur par défaut" sera cochée. Bien que votre solution puisse fonctionner, je n'aime pas personnellement utiliser les requêtes SQL directes.
Simon
Excusez-moi, j'ai mal lu votre réponse et j'ai pensé que vous demandiez à OP de mettre toutes les valeurs par défaut au lieu de false. Votre solution fonctionne :)
Paras Sood
5
Veuillez noter que «Ce n'est pas vrai» fait référence à un commentaire sur la réponse de Simon qui a maintenant été supprimé. La solution fonctionne.
Fabian Schmengler du
@fschmengler Paras répondrait-il au travail pour montrer les images sur le front-end? J'ai le même problème avec ma nouvelle boutique tous les produits et images sont là mais ils ne sont pas sélectionnés pour être utilisés par défaut.
thismethod
@thismethod non, c'est quelque chose de différent. Il y a peut-être déjà une question, sinon posez-en une nouvelle
Fabian Schmengler
7

Rejoindre un peu tard, mais je n'ai pas vraiment aimé l'une des réponses ci-dessus.

  1. La réponse de Simons de parcourir la collection de produits est incroyablement lente et inefficace, mais elle utilise au moins Magento
  2. La réponse de ParasSood de faire des modifications directes sur la base de données est un peu effrayante et peu utilisable si vous voulez que cela soit un peu une fonctionnalité automatisée.

Voici ma tentative, pas entièrement testée, mais elle semble faire ce dont j'ai besoin.

/**
 * If given store code will reset only that store, otherwise will set all stores to "use default"
 *
 * If given product ids will reset only those products, otherwise all products will be set to "use default"
 *
 * @param $attributeCode
 * @param null $storeCode
 * @param null $productIds
 *
 */
public function forceProductsToUseDefault($attributeCode, $storeCode = null, $productIds = null)
{
    $conditions = array();

    if (is_null($storeCode)) {
        $conditions['store_id != ?'] = Mage_Core_Model_App::ADMIN_STORE_ID;
    } else {
        $store = Mage::app()->getStore($storeCode);
        if (!$store instanceof Mage_Core_Model_Store || !$store->getId()) {
            Mage::throwException("Store with code not found: $storeCode");
        }
        $conditions['store_id = ?' ] = $store->getId();
    }

    if (!is_null($productIds)) {
        $conditions['entity_id in(?)'] = $productIds;
    }

    $attribute = Mage::getModel('eav/entity_attribute')
        ->loadByCode(Mage_Catalog_Model_Product::ENTITY, $attributeCode);
    if (!$attribute instanceof Mage_Eav_Model_Entity_Attribute_Abstract || !$attribute->getId()) {
        Mage::throwException("Attribute with code not found: $attributeCode");
    }
    $conditions['attribute_id = ?'] = $attribute->getId();

    $coreResource = Mage::getSingleton('core/resource');

    $coreResource->getConnection('core_write')->delete(
        $coreResource->getTableName(array('catalog/product', $attribute->getData('backend_type'))),
        $conditions
    );
}
Luke Rodgers
la source
Pourquoi lançons-nous une erreur de syntaxe à la ligne 14? @Luke Rodgers
Supplément du
Quelle est l'erreur?
Luke Rodgers
C'est corrigé maintenant, mais cela ne fonctionne jamais correctement et se termine sur mon développeur. environnement. Aucune suggestion?
Supplément
Je ne peux pas aider sans l'erreur réelle :)
Luke Rodgers
un guide sur la façon d'utiliser ce code? puis-je l'utiliser comme script autonome?
Kris Wen
3

Vous pouvez utiliser événement core_block_abstract_to_html_before adminhtml pour ajouter les cases à cocher requises pour chaque attribut dans le formulaire de mise à jour en masse de l'administrateur.

protected $_controllers = array(
    'attribute', 
    'catalog_product_action_attribute'
    );


public function htmlBefore(Varien_Event_Observer $observer)
{
        $block = $observer->getBlock();

        if (!isset($block)) {
            return $this;
        }

        $request = Mage::app()->getRequest();
        $storeId = $request->getParam('store');

        if ($storeId != 0) {
            if(in_array($request->getControllerName(), $this->_controllers) 
                    && $request->getActionName() == 'edit') {
                // Add use_default checkboxes
                if ($block instanceof Mage_Adminhtml_Block_Catalog_Form_Renderer_Fieldset_Element) {
                    $block->getDataObject()->setId('empty');
                    $block->getDataObject()->setStoreId($storeId);
                    $block->getDataObject()->setExistsStoreValueFlag($block->getAttribute()->getAttributeCode());
                }
            }
        }
}

Ensuite, vous devrez utiliser événement catalog_product_attribute_update_before pour supprimer les valeurs des tables EAV pour une vue de magasin spécifique, uniquement pour les attributs dont la case à cocher que vous avez injectée précédemment avec core_block_abstract_to_html_before est définie comme vérifiée.

J'espère que cela pourra aider.

Ce module fait exactement cela: http://mageinn.com/product/adminextra/ Il est également possible de réinitialiser l' attribut ' url_key ' avec ce module.

kolucciy
la source